我为这篇冗长的文章道歉。我在尽可能小的情况下尽可能减少了问题的发生。非常奇怪的问题通过C#中的套接字发送数据#
好吧,这让我疯狂。我有一个客户端和一个服务器程序,都在C#中。服务器通过Socket.Send()向客户端发送数据。客户端通过Socket.BeginReceive和Socket.Receive接收数据。我的伪协议如下所示:服务器发送一个二字(短)值,表示实际数据的长度,紧接着是实际数据。客户端异步读取前两个字节,将字节转换为短字节,并立即从套接字同步读取多个字节。
现在这工作正常每隔几秒钟左右一个周期,但当我提高速度,事情变得怪异。当它试图从两字节长度读取时,客户端似乎会随机读取实际数据。然后它会尝试将这些任意两个字节转换为一个短的值,导致完全不正确的值,从而导致崩溃。以下代码来自我的程序,但修剪为仅显示重要的行。
private static object myLock = new object();
private static bool sendData(Socket sock, String prefix, byte[] data)
{
lock(myLock){
try
{
// prefix is always a 4-bytes string
// encoder is an ASCIIEncoding object
byte[] prefixBytes = encoder.GetBytes(prefix);
short length = (short)(prefixBytes.Length + data.Length);
sock.Send(BitConverter.GetBytes(length));
sock.Send(prefixBytes);
sock.Send(data);
return true;
}
catch(Exception e){/*blah blah blah*/}
}
}
客户端的方法,用于接收数据:
private static object myLock = new object();
private void receiveData(IAsyncResult result)
{
lock(myLock){
byte[] buffer = new byte[1024];
Socket sock = result.AsyncState as Socket;
try
{
sock.EndReceive(result);
short n = BitConverter.ToInt16(smallBuffer, 0);
// smallBuffer is a 2-byte array
// Receive n bytes
sock.Receive(buffer, n, SocketFlags.None);
// Determine the prefix. encoder is an ASCIIEncoding object
String prefix = encoder.GetString(buffer, 0, 4);
// Code to process the data goes here
sock.BeginReceive(smallBuffer, 0, 2, SocketFlags.None, receiveData, sock);
}
catch(Exception e){/*blah blah blah*/}
}
}
服务器端代码以重新创建可靠的问题:
byte[] b = new byte[1020]; // arbitrary length
for (int i = 0; i < b.Length; i++)
b[i] = 7; // arbitrary value of 7
while (true)
{
sendData(socket, "PRFX", b);
// socket is a Socket connected to a client running the same code as above
// "PRFX" is an arbitrary 4-character string that will be sent
}
用于发送数据的服务器端方法
看上面的代码,可以确定服务器会永远发送数字1024,长度总数据(包括前缀)作为一个短(0x400),后跟ASCII码二进制中的“PRFX”,后面跟着一堆7(0x07)。客户端将永远读取前两个字节(0x400),将其解释为1024,将该值存储为n,然后从流中读取1024个字节。
这确实是它为前40次迭代所做的,但客户端会自动读取前两个字节,并将它们解释为1799,而不是1024!十六进制中的1799是0x0707,这是连续两个7的!这是数据,而不是长度!这两个字节发生了什么?这发生在无论我放在字节数组中的任何值上,我只选择了7,因为很容易看到与1799的相关性。
如果您仍在阅读这一点,我赞扬您的奉献精神。
一些重要的观察结果:
- 降低b的长度发生之前这个问题,但不会阻止问题发生
- 添加循环的每次迭代之间的显著延迟将增加迭代的次数可能会防止发生问题
- This DOES NOT在同一主机上同时使用客户端和服务器并通过回送地址连接时发生。
如上所述,这让我疯狂!我总是能够解决我的编程问题,但这个问题已经让我完全陷入困境。所以我在这里恳求任何有关这个问题的建议或知识。
谢谢。
这是我曾经有过的一个问题。尝试在while循环中读取网络中的数据,直到读取“length”参数中指定的数据量 – Kurru 2011-01-31 19:33:04