微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Tcp 客户端不发送第二个响应数据包

如何解决Tcp 客户端不发送第二个响应数据包

我正在研究一个跟踪设备,当它发送数据包并且服务器确认它时它工作正常,但有一种情况,该设备需要对一个数据包进行两次确认。 我正在发送两个,但我不知道为什么设备不接受它,因为之后设备正在发送登录数据包。

注意:登录数据包是设备在连接开始时以及设备没有收到所需确认时发送的数据包。有人可以帮我解决这个问题吗?

这是服务器端代码

    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 丢弃。

反过来也可能发生;无法保证您通过一次读取调用读取完整的应用程序级数据包。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。