我已经研究了这么多个小时,尝试了很多不同的事情来解决这个问题,但是我被困住了。我正在尝试创建一个可以从多个线程访问的异步套接字。它往往运行正常,直到我有几个线程试图接近同一时间发送。发送时没有错误,唯一的问题是当EndReceive()尝试读取数据时,它返回0字节,套接字错误是“成功”。我读过这意味着这是一个优雅的关闭,服务器没有更多的数据要发送,但我连接的服务器类型应该永远不会发送所有数据,它不是那种类型的服务器。应始终存在要读取的数据,不应该关闭。
我用来发送一些System.Threading.Timers但我读过的线程并不完全是线程安全的。我也尝试过System.Timers.Timer,但结果相同。我也尝试过只使用1个线程一次发送大量数据包,之间睡眠时间为100毫秒,我会得到相同的结果。
接收代码如下。对于发送,我已经尝试过定期阻止Send和BeginSend,它没有什么区别。
void Receive()
{
try
{
if (_datacb == null)
_datacb = new AsyncCallback(OnRecvData);
byte[] buffer = new byte[FBufferSize];
FSocket.BeginReceive(buffer, 0, FBufferSize, SocketFlags.None, _datacb, buffer);
}
catch (SocketException ex)
{
OnSocketError(ex);
}
}
void OnRecvData(IAsyncResult ar)
{
try
{
SocketError err;
int bytesRead = FSocket.EndReceive(ar, out err);
if (bytesRead == 0)
{
throw new SocketException();
}
byte[] buffer = ar.AsyncState as byte[];
FReceived.AddBytes(buffer, bytesRead);
ByteBuffer message = FReceived.GetNextMessage();
while (message != null)
{
Process(message);
message = FReceived.GetNextMessage();
}
}
catch (SocketException ex)
{
OnSocketError(ex);
}
Receive();
}
我认为它可能是服务器只是关闭套接字发送太快,但我实际上有一个我在VS2008制作的阻止版本,我能够使用50个不同的定时器,每秒发送1个数据包,我没有断开连接。我在VS2010中尝试了几乎相同的代码,且bytesRead为0.我也尝试了VS2008中的asyc套接字代码,只是为了看看是否有一些奇怪的事情,但在VS2008中,它仍然给了我bytesRead == 0.对于阻塞代码,它没有' t断开我:
tcpClient = new TcpClient(host, 443);
networkStream = tcpClient.GetStream();
mReader = new BinaryReader(networkStream);
mWriter = new BinaryWriter(networkStream);
receiveMessage = new Thread(new ThreadStart(ReceiveMessages));
receiveMessage.Start();
private void ReceiveMessages()
{
while (true)
{
if ((tcpClient != null) && (tcpClient.Connected))
{
if (tcpClient.Available >= 4)
{
if (!isConnected) isConnected = true;
try
{
ByteBuffer message = new ByteBuffer();
message.AddBytes(mReader.ReadBytes(4));
int mSize = message.ReadInt();
message.AddBytes(mReader.ReadBytes(mSize - 4));
processor.Process(message);
}
catch (Exception ex)
{
Print("Recv Msg: " + ex.Message);
}
}
Thread.Sleep(1);
}
}
发送:
mWriter.Write(send);
mWriter.Flush();
不太满意,因为它使用了大量的CPU。我尝试了其他方法来阻止这样的套接字而不使用尽可能多的CPU,但它们也会断开连接。
答案 0 :(得分:0)
套接字不是线程安全的。见here
您应该同步对套接字的访问权限,或让一个线程处理所有这些(我认为它更干净,并且还可以使调试更容易)。
答案 1 :(得分:0)
显然它与实际发送无关,而是与发送的数据无关。服务器期望与每个数据包一起发送某种指纹,这是一种加密方式。每次获得指纹时,都必须调整一个值。我正在对实际发送进行线程锁定,但它需要锁定在计算指纹的部分。一些数据包发送时带有错误的指纹,因为它们是按顺序计算的,因此服务器以这种方式断开连接。
我可能应该在我的问题中提到过,但我并不认为它是相关的。
答案 2 :(得分:0)
套接字可以读取0个字节。这个是正常的。您需要做的是再次读取,直到您获得完整的数据包。当人们期望套接字读取与服务器发送的字节数相同的字节数时,这是一个常见的错误。是的,这通常是锻炼。但实际上数据可能会碎片化,你只会得到数据块。因此,您的代码应该准备好从套接字组装数据块,因为数据碎片迫在眉睫。