问题描述
我正在研究一个跟踪设备,当它发送数据包并且服务器确认它时它工作正常,但有一种情况,该设备需要对一个数据包进行两次确认。 我正在发送两个,但我不知道为什么设备不接受它,因为之后设备正在发送登录数据包。
注意:登录数据包是设备在连接开始时以及设备没有收到所需确认时发送的数据包。有人可以帮我解决这个问题吗?
这是服务器端代码。
public async Task ParseAvlDataAsync(TcpClient client,NetworkStream stream,byte[] array)
{
var resp = Utils.GetinformationContent(array);
if (resp.Item2)
{
string imei = Utils.BytesToString(resp.Item1);
Console.WriteLine("IMEI received: " + imei);
Console.WriteLine("--------------------------------------------");
var response = Utils.CreateResponse(array);
await stream.WriteAsync(response,response.Length).ConfigureAwait(false);
Console.WriteLine("Login response sent");
while (client.Connected)
{
stream = client.GetStream();
byte[] buffer = new byte[client.ReceiveBufferSize];
await stream.ReadAsync(buffer,buffer.Length).ConfigureAwait(false);
//it can be Location data,status info,alarm data
//if it is location data then response will not be sent to the server
Console.WriteLine(string.Format("Get {0} Packet",(PROTOCOL_NUMBER)buffer[3]));
if ((PROTOCOL_NUMBER)buffer[3] != PROTOCOL_NUMBER.LOCATION_DATA && (PROTOCOL_NUMBER)buffer[3] != PROTOCOL_NUMBER.STRING_INFO)
{
if (Utils.IsVaidProtocol((PROTOCOL_NUMBER)buffer[3]))
{
//send first response for every packet
response = Utils.CreateResponse(buffer);
if ((PROTOCOL_NUMBER)buffer[3] == PROTOCOL_NUMBER.ALARM_DATA)
{
//send second response of alarm packet
Utils.SendAlarmSecondResponse(client,buffer);
}
await stream.WriteAsync(response,response.Length).ConfigureAwait(false);
Console.WriteLine(string.Format("{0} response sent.",(PROTOCOL_NUMBER)buffer[3]));
}
else
{
client.Close();
client.dispose();
Console.WriteLine("Invalid packet recieved : " + buffer[3]);
Console.WriteLine(Utils.BytesToString(buffer));
}
}
if (Utils.IsVaidProtocol((PROTOCOL_NUMBER)buffer[3]) && (PROTOCOL_NUMBER)buffer[3] != PROTOCOL_NUMBER.LOGIN_MESSAGE)
{
Parser.Parse((PROTOCOL_NUMBER)buffer[3],imei,stream,buffer);
}
else if ((PROTOCOL_NUMBER)buffer[3] != PROTOCOL_NUMBER.LOGIN_MESSAGE)
{
client.Close();
client.dispose();
Console.WriteLine("Invalid protocol : " + (PROTOCOL_NUMBER)buffer[3]);
}
}
}
}
public async static void SendAlarmSecondResponse(TcpClient client,byte[] buffer)
{
try
{
NetworkStream stream = client.GetStream();
UInt16 sendCRC = 0;
int messageLength = buffer[2];
//skip start bytes,message length. then go back 4 bytes (CRC and serial number)
byte[] serialNumber = buffer.Skip(2 + 1 + messageLength - 4).Take(2).ToArray();
int alarmDataAddresspacketLen = alarmDataAddressResponse.Length - 5;
alarmDataAddressResponse[2] = (byte)(alarmDataAddresspacketLen & 0xFF);
serialNumber.copyTo(alarmDataAddressResponse,alarmDataAddresspacketLen - 1);
sendCRC = CRCBytes(alarmDataAddressResponse.Skip(2).Take(alarmDataAddresspacketLen - 1).ToArray());
alarmDataAddressResponse[alarmDataAddresspacketLen + 1] = (byte)((sendCRC >> 8) & 0xFF);
alarmDataAddressResponse[alarmDataAddresspacketLen + 2] = (byte)((sendCRC) & 0xFF);
await stream.WriteAsync(alarmDataAddressResponse,alarmDataAddressResponse.Length).ConfigureAwait(false);
}
catch (Exception ex)
{
throw ex;
}
}
解决方法
TCP 不是面向消息的,而是面向流的。
您可能将多个应用程序级“数据包”读入 buffer
,并且您只解析第一个,然后将其余的 buffer
丢弃。
反过来也可能发生;无法保证您通过一次读取调用读取完整的应用程序级数据包。