C# 从TCP客户端接收数据时出错
我已经编写了一个应用程序,它监听一个端口并接收一些数据包,根据我的定制协议,数据包是49字节到1500字节,我可以从数据包中的数据长度来判断。我应该以不同的方式解释和处理49字节数据包和更大数据包中的数据 问题是,当我收到小于1374字节的数据包时,一切正常,但当数据包长度变长时,我收到以下异常,我还丢失了数据的最后4个字节(我用1384字节的数据包进行了测试,最后4个字节丢失了) 提出的例外情况: 索引超出范围。必须为非负数且小于集合的大小。 参数名称:startIndex 每个49字节的数据包有35字节的数据,较大数据包的数据长度是不确定的(因为压缩) 我发现有时最后4个字节在一个单独的“字节”和“结果”变量中,这意味着它们被视为新的数据包,而不是附加到它们所属的数据包上 以下是接收数据的代码:C# 从TCP客户端接收数据时出错,c#,sockets,tcpclient,tcplistener,tcp-ip,C#,Sockets,Tcpclient,Tcplistener,Tcp Ip,我已经编写了一个应用程序,它监听一个端口并接收一些数据包,根据我的定制协议,数据包是49字节到1500字节,我可以从数据包中的数据长度来判断。我应该以不同的方式解释和处理49字节数据包和更大数据包中的数据 问题是,当我收到小于1374字节的数据包时,一切正常,但当数据包长度变长时,我收到以下异常,我还丢失了数据的最后4个字节(我用1384字节的数据包进行了测试,最后4个字节丢失了) 提出的例外情况: 索引超出范围。必须为非负数且小于集合的大小。 参数名称:startIndex 每个49字节的数据
TcpClient Client = obj as TcpClient;
EndPoint ep = Client.Client.RemoteEndPoint;
List<Byte> result = new List<byte>();
result.Capacity = 2000;
try
{
NetworkStream stream = Client.GetStream();
int i = 49;
while ((i = stream.Read(bytes, 0,49)) != 0)
{
for (int id = 0; id < i; id++)
{
result.Add(bytes[id]);
}
//reading data length to determine packet length
byte[] tmp = new byte[2];
tmp = BitConverter.GetBytes(BitConverter.ToUInt16(result.ToArray(), 9));
if (BitConverter.IsLittleEndian)
{
Array.Reverse(tmp);
}
Int16 l = BitConverter.ToInt16(tmp, 0);
if (l>35)
{
stream.Read(bytes, result.Count, l - 35);
for (int id = 49; id <((l-35)+49); id++)
{
result.Add(bytes[id]);
}
if (this.TCPDataReceivedHandler != null)
{
this.TCPDataReceivedHandler(ep, result.Count, result.ToArray());
result.Clear();
Array.Clear(bytes, 0, 2000);
result.Capacity = 2000;
}
}
else
{
if (this.TCPDataReceivedHandler != null)
{
this.TCPDataReceivedHandler(ep, result.Count, result.ToArray());
result.Clear();
Array.Clear(bytes, 0, 2000);
result.Capacity = 2000;
}
}
}
System.Diagnostics.Debug.WriteLine("client Close");
Client.Close();
}
catch (System.Exception ex)
{
throw ex;
}
finally
{
Client.Close();
this.clients.Remove(Client);
}
TcpClient Client=obj作为TcpClient;
端点ep=Client.Client.RemoteEndPoint;
列表结果=新列表();
结果:容量=2000;
尝试
{
NetworkStream=Client.GetStream();
int i=49;
而((i=stream.Read(字节,0,49))!=0)
{
for(int-id=0;id35)
{
读取(字节,结果,计数,l-35);
对于(int id=49;id使用TCP时,您必须记住,您输入的数据块的大小不能保证与您在接收端输出的数据块的大小相同。TCP是一种流协议,因此它保证相同的字节以与发送相同的顺序到达另一端(如果没有,套接字连接将被重置)。TCP不会在调用send()
之间保持任何类型的块边界,并且块可以根据网络条件任意分割或合并
您的接收器必须准备好处理从调用stream.Read()
接收任何数量的数据,但您的代码似乎没有这样做。例如,即使stream.Read()
一次只接收一个字节。谢谢Greg,但如果我继续从stream.read()读取数据,如何确保数据包不会相互混合不注意我的数据包中的数据长度字段?数据包以短时间序列连续发送。看起来您的协议有一个标头,指定了以下数据块的长度。因此,对于当前数据块只读取那么多,然后循环到顶部并读取下一个数据块的长度标头。亲爱的Greg、 我尝试使用您的建议,但没有成功,我仍然无法接收超过1380字节的数据。您更改了代码,但仍然存在相同的问题。每次调用stream.Read()时
,您必须处理接收的字节数少于要求的字节数的情况。当您要求11个字节时,您可能会收到1到11个字节之间的任何字节。
NetworkStream stream = Client.GetStream();
int bytesread = 0, OffsetTemp = 0;
while (stream.CanRead)
{
OffsetTemp = 0;
bytesread += stream.Read(bytess, OffsetTemp, 11);
OffsetTemp = OffsetTemp + 11;
byte[] tmp = new byte[2];
tmp = BitConverter.GetBytes(BitConverter.ToUInt16(bytess.ToArray(), 9));
if (BitConverter.IsLittleEndian)
{
Array.Reverse(tmp);
}
Int16 l = BitConverter.ToInt16(tmp, 0);
bytesread += stream.Read(bytess, OffsetTemp++, 11 + l + 3);
for (int id = 0; id < l + 14; id++)
{
result.Add(bytess[id]);
}
if (this.TCPDataReceivedHandler != null)
{
this.TCPDataReceivedHandler(ep, result.Count, result.ToArray());
result.Clear();
Array.Clear(bytess, 0, 2000);
}
}