0

我有一个代码(假设是一个简单的聊天应用程序),我使用了同步的 Tcp。但是由于异步方式更好,虽然它更难设置,所以我决定将方式从同步更改为异步。但现在我在使用异步时遇到了一些问题。

  1. 缓冲区大小:我知道我们需要考虑有限大小的字节才能从对等方获取字节。我读了很多文章,但我的问题没有解决,我有一个非常简单但毫无价值的方法来解决这个问题,在每条消息的末尾加上一个字符;然后接收者可以理解何时完全接收到消息。但我有另一个问题阻止我进一步执行这种方法来解决它对我的另一个问题。

让我通过以下代码解释我的问题:

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 是从对等方接收到的字符串。并且使用同步方式的输出必须是

你好

再见

但是以异步方式,我将其作为一条消息而不是两条消息接收,因此将其打印

你好再见

此致,佩曼·莫尔塔扎维

4

2 回答 2

4

我必须说我真的不同意简单地切换到同步套接字来克服这个问题。更好的方法是使用Queue<string>(例如)在发送呼叫时将消息放入的位置。

然后你有你的异步套接字从这个队列中取出数据包,并在当前一个完成发送时发送下一个,直到队列为空。

然后您可以选择在队列中再次出现消息之前不再调用 BeginSend。

于 2012-12-14T12:38:28.817 回答
2

使用同步调用,您可以保证在发送第二条消息之前完全发送第一条消息。但是,使用异步方法,您只是将两条消息添加到传出队列中,等待发送。如果您碰巧在正确的时间点击它,它可能会将它们作为两条单独的消息发送,但由于您将它们都添加得如此之快,它很可能会同时发送它们。如果您将 TCP/IP 套接字通信视为单个持续的数据流,那么您的情况会好得多。您需要以一种可以确定它们的开始和结束位置的方式来格式化您的消息。当您通过套接字接收数据时,您应该继续将接收到的消息添加到缓冲区,直到您确定(基于数据的格式)您已收到完整的消息。您不应该依赖从套接字读取的每次消息都是一条完整的消息。您应该期望它可能只是部分消息,甚至是多条消息。

于 2012-05-17T13:55:04.610 回答