最近笔者需要完成ESP8266与PC之间的无线通信,于是选择ESP8266作TCP服务器,PC上作TCP客户端,通过C#开发客户端程序。
问题描述
TCP服务器(ESP8266)数据发送函数如下。
void GetSerialToClient(void)
{
if(Serial.available())
{
uint8_t i;
uint32_t len = Serial.available();
uint8_t sbuf[len];
Serial.readBytes(sbuf, len);
for (i = 0; i < MAX_SRV_CLIENTS; i++)
{
if (serverClients[i] && serverClients[i].connected())
{
serverClients[i].write(sbuf, len);
Serial.write(sbuf, len);
delay(1);
}
}
}
}
TCP客户端(C#)数据接收函数如下。
private void RecMsg()
{ //持续监听服务端发来的消息
while (true)
{
try
{
byte[] arrRecMsg = new byte[1024 * 1024];
int length = socketClient.Receive(arrRecMsg);
//string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length);
//txtMsg.AppendText(strRecMsg);
//将发送的信息显示到聊天内容文本框中
for (int i = 0; i < length; i++)//将字符串转换成十六进制数显示到文本框内
{
string str = Convert.ToString(arrRecMsg[i], 16).ToUpper();
this.txtMsg.AppendText((str.Length == 1 ? "0" + str + " " : str + " "));
}
this.txtMsg.AppendText("\r\n" + "接收到数据!长度为" + Convert.ToString(length) + "\r\n");
}
catch (Exception ex)
{
Console.WriteLine("错误信息:" + ex.ToString());
this.txtMsg.AppendText("远程服务器已中断连接!" + "\r\n");
this.btnListenServer.Enabled = true;
break;
}
}
}
程序运行结果如下图。
笔者通过串口先后发送FF 11 22 33 44 55 66 77和FF 11 22 33到ESP8266,ESP8266端再通过网络转发数据到TCP客户端。从左侧程序运行框可以看出来,每一次发送数据,接收端都显示接收到两次数据,第一次长度都是1,数据都是FF,第二次是除FF后面的数据。
这样的运行效果导致,笔者在使用自定通信协议时,客户端将发送端的完整的一帧数据分成了两段去接收,无法完整地接收到一帧数据,这样在对一帧数据进行解析时带来了困难。
在这个通信系统中,有可能是服务器端serverClients[i].write(sbuf, len)函数的问题,也可能是客户端的接收程序问题。希望有对网络通信熟悉的读者解惑。
解决问题
目前,暂时性的解决问题的办法是,服务器端发送数据时,会在一帧数据前额外填上一个字节数据(FF),然后在客户端接收程序中判断第一个是否为FF,如果是FF则不进行数据解析,否则将进行数据解析。