我正在开发一个异步接受 TCP 连接 (BeginAccept/EndAccept) 和数据 (BeginReceive/EndReceive) 的服务器应用程序。该协议(protocol)要求在发送下一条消息之前,只要发现 EOM 字符就发送 ACK。接受和接收正在工作,但发送应用程序没有收到 ACK(同步发送)。
private void _receiveTransfer(IAsyncResult result)
{
SocketState state = result.AsyncState as SocketState;
int bytesReceived = state.Socket.EndReceive(result);
if (bytesReceived == 0)
{
state.Socket.Close();
return;
}
state.Offset += bytesReceived;
state.Stream.Write(state.Buffer, 0, bytesReceived);
if (state.Buffer[bytesReceived - 1] == 13)
{
// process message
Messages.IMessage message = null;
try
{
var value = state.Stream.ToArray();
// do some work
var completed = true;
if (completed)
{
// send positive ACK
var ackMessage = string.Format(ack, message.TimeStamp.ToString("yyyyMMddhhmm"), message.MessageType, message.Id, "AA", message.Id);
var buffer = ASCIIEncoding.ASCII.GetBytes(ackMessage);
int bytesSent = state.Socket.Send(buffer, 0, buffer.Length, SocketFlags.None);
}
else
{
// send rejected ACK
var ackMessage = string.Format(ack, message.TimeStamp.ToString("yyyyMMddhhmm"), message.MessageType, message.Id, "AR", message.Id);
state.Socket.Send(ASCIIEncoding.ASCII.GetBytes(ackMessage));
}
}
catch (Exception e)
{
// log exception
// send error ACK
if (message != null)
{
var ackMessage = string.Format(ack, DateTime.Now.ToString("yyyyMMddhhmm"), message.MessageType, message.Id, "AE", message.Id);
state.Socket.Send(ASCIIEncoding.ASCII.GetBytes(ackMessage));
}
}
}
state.Socket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, new AsyncCallback(_receiveTransfer), state);
}
state.Socket.Send 返回正确的字节数,但在处理套接字之前不会收到数据。
欢迎提出建议。
最佳答案
- 你不应该做任何与异步完成例程同步的事情。在负载下,您最终可能会劫持线程池中的所有 IO 完成线程并严重损害性能,甚至包括完全 IO 死锁。所以不要从异步回调中同步发送 ACK。
- 使用前导码的协议(protocol)和格式比使用终止符的协议(protocol)和格式更容易管理。 IE。在固定大小的消息头中写入消息的长度,而不是检测终止符\0x13。当然,如果协议(protocol)一开始就在您的控制之下,这就适用。
至于您的问题,您没有说明您发布的相同代码是否也在客户端。
关于c# - 直到 socket.Close 才收到 Windows socket.Send 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2269133/