我有一个代码(假设一个简单的聊天应用程序),我使用Tcp同步。但由于Async方式更好,虽然设置起来比较困难,但我决定改变从同步到异步的方式。但现在我在使用异步时遇到了一些问题。
让我通过以下代码解释我的问题:
public void Send(byte[] message, Socket connection)
{
connection.BeginSend(message,
0,
message.Length,
SocketFlags.None,
new AsyncCallback(OnSend),
connection);
}
在OnSend方法中,我只使用 connection.EndSend(result),其中结果是IAsyncResult。但是当我然后像下面的代码一样调用Send方法两次时,OnReceive回调将接收它们作为单个消息。
Send(Encoding.Unicode.GetBytes("Hello"));
Send(Encoding.Unicode.GetBytes("Bye"));
我的OnReceiveMethod将使用 Console.WriteLine(message); 其中message是从peer收到的字符串。并且使用同步方式的输出必须是
你好
再见
但是以异步方式我收到它作为一条消息而不是两条消息,因此它被打印
HelloBye
真诚的,你的, Peyman Mortazavi
答案 0 :(得分:4)
我必须说我不同意简单地切换到同步套接字来克服这个问题。一个更好的方法是使用Queue<string>
(例如),在调用send时将消息放入其中。
然后让你的异步套接字从这个队列中出队,并在当前队列完成发送时发送下一个,直到队列为空。
然后您可以选择不再次调用BeginSend,直到队列中再次显示消息。
答案 1 :(得分:2)
使用同步呼叫,您可以保证在发送第二条消息之前完全发送第一条消息。但是,使用异步方法,您只需将两条消息添加到传出队列,等待发送。如果您碰巧在正确的时间点击它,它可能会将它们作为两个单独的消息发送,但由于您将它们添加得如此之快,因此很可能将两者一起发送。如果您认为TCP / IP套接字通信是一个持续的数据流,那么您将会好得多。您需要以可以确定其开始和结束位置的方式格式化消息。当您通过套接字接收数据时,应该继续将收到的消息添加到缓冲区,直到您确定(基于数据的格式)您已收到完整的消息。您不应该依赖套接字中的每个读取作为单个完整的消息。您应该期望它可能只是部分消息甚至是多条消息。