我们期望实现Arduino+ESP8266来实现终端和服务器之间的远程通信,在文章 《Arduino+ESP8266上传数据到服务器》中,实现了将终端的数据上传到服务器,在文章《Arduino+ESP8266接收服务器信息》中,实现了终端手动接收服务器的信息。这两篇文章都只是一个铺垫,没有真正的实现远程通信的功能。我们在编程测试过程中,始终无法实现这种基于TCP协议的远程通信(可能是代码的bug,也可能是其他未知的原因),我们在之前的一文章《Arduino+ESP8266接收服务器信息——源代码分析》中,也专门对源码进行了分析,暂时没有找到原因。如果读者知道其中的原因,请不吝赐教。换一个角度,我们期望通过基于UDP协议的远程通信,在文章《TCP,UDP通信使用场景及区别比较》中,对于TCP和UDP协议进行了简单的比较,同时在我们在Eclipse上模拟实现了终端和服务器间基于UDP的通信。本文,我们将实现Arduino+ESP8266搭建的终端平台和服务器之间的基于UDP的远程通信。 服务器源代码
package udpserver.damuchacha;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class UDPServer {
public static void main(String[] args) throws IOException {
//接收客户端发送的数据
DatagramSocket socket = new DatagramSocket(8800);
// 1.创建服务器端DatagramSocket,指定端口
// 2.创建数据报,用于接收客户端发送的数据
byte[] data = new byte[1024];//创建字节数组,指定接收的数据包的大小
DatagramPacket packet = new DatagramPacket(data, data.length);
// 3.接收客户端发送的数据
System.err.println("Server:");//输出服务器的标识
while(true) {//通过循环不停的向客户端发送数据和接收数据
socket.receive(packet);// 此方法在接收到数据报之前会一直阻塞
// 4.读取数据
String info = new String(data, 0, packet.getLength());//创建字符串对象
System.out.println("服务器接收到客户端的信息是:" + info);//输出提示信息
//向客户端响应数据
// 1.定义客户端的地址、端口号、数据
System.out.println("回复客户端的消息:");
InetAddress address = packet.getAddress();
//获取发送端的地址
int port = packet.getPort();
//获取 发送端进程所绑定的端口
Scanner scanner = new Scanner(System.in);
//从键盘接受数据
String send = scanner.nextLine();
//nextLine方式接受字符串
byte[] data2 = send.getBytes();
//将接收到的数据转换为字节数组
DatagramPacket packet2 = new DatagramPacket(data2, data2.length,address,port);
// 2.创建数据报,包含响应的数据信息
socket.send(packet2);
// 3.响应客户端
}
}
}
客户端源代码
#include "ESP8266.h"
#include<SoftwareSerial.h>
#define WIFI_TX 9
#define WIFI_RX 8
#define SSID "Destiny Child"
#define PASSWORD "di*********n"
#define HOST_NAME "172.20.10.9"
#define HOST_PORT 8800
SoftwareSerial mySerial(WIFI_RX,WIFI_TX);
ESP8266 wifi(mySerial,115200);
void setup(void)
{
Serial.begin(230400);
Serial.print("setup begin\r\n");
Serial.print("FW Version:");
Serial.println(wifi.getVersion().c_str());
// 设置操作模式
while(wifi.setOprToStationSoftAP()==false){
Serial.print("waiting for setting operating mode station + softap ...\r\n");
delay(100);
}
Serial.print("operating mode station + softap ok\r\n");
//连接WiFi
while(wifi.joinAP(SSID, PASSWORD)==false){
Serial.print("waiting for joining AP...\r\n");
delay(100);
}
Serial.print("Join AP success\r\n");
//WiFi连接成功后打印IP地址
Serial.print("IP:");
Serial.println( wifi.getLocalIP().c_str());
//设置连接模式
while(wifi.disableMUX()==false){
Serial.print("waiting for single connecting mode TCP or UDP ...\r\n");
delay(100);
}
Serial.print("single mode ok\r\n");
Serial.print("setup success\r\n");
}
void loop(void)
{
uint8_t buffer[128] = {0};
while(wifi.registerUDP(HOST_NAME, HOST_PORT)==false){
Serial.print("register udp err\r\n");
delay(100);
}
Serial.print("register udp ok\r\n");
char *hello = "Hello, this is client!";
wifi.send((const uint8_t*)hello, strlen(hello));//发送数据
uint32_t len = wifi.recv(buffer, sizeof(buffer), 10000);//接收数据
if (len > 0) { //打印数据
Serial.print("Received:[");
for(uint32_t i = 0; i < len; i++) {
Serial.print((char)buffer);
}
Serial.print("]\r\n");
}
if (wifi.unregisterUDP()) {
Serial.print("unregister udp ok\r\n");
} else {
Serial.print("unregister udp err\r\n");
}
delay(5000);
}
服务器输出
见图1
客户端输出
见图2
通过服务器和终端的输出结果可以看出,服务器和终端之间能够成功的进行通信。不足的地方是,终端有时候会漏接服务器的信息,有时候接收到的信息会出错。后续的学习过程我们会继续进行完善。
完 2018/8/27
|