我正在开发一个异步接受TCP连接(BeginAccept / EndAccept)和数据(BeginReceive / EndReceive)的服务器应用程序。该协议要求在发送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返回正确的字节数,但在放置套接字之前不会收到数据。
建议表示赞赏。
答案 0 :(得分:2)
至于您的问题,您没有指定您发布的代码是否也在客户端。
答案 1 :(得分:0)
你给它多久了?网络堆栈可以缓冲,这可能会延迟传输。来自MSDN:
为了提高网络效率, 基础系统可能会延迟 传输直到显着 收集的传出数据量。 成功完成发送 方法意味着底层 系统有空间缓冲你的 网络发送的数据。
您可能想尝试使用IOControl方法进行刷新。
修改
实际上,IOControl flush会杀死缓冲区。您可能需要查看Two Generals Problem以查看您的协议是否存在一些固有问题。
答案 2 :(得分:0)
尝试设置TCP_NODELAY套接字选项
答案 3 :(得分:0)
您是否已将套接字上的NoDelay
属性设置为true
?设置为false
(默认值)时,数据在发送之前最多缓冲200毫秒。原因是通过限制发送的数据包数量来减少网络流量。将NoDelay
设置为true
会强制更快地发送数据。