【问题标题】:Issue receiving messages using Tcp with Async使用带有异步的 Tcp 接收消息问题
【发布时间】:2012-05-17 13:13:36
【问题描述】:

我有一个代码(假设是一个简单的聊天应用程序),我使用带有同步的 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 是从对等方接收到的字符串。并且使用同步方式的输出必须是

你好

再见

但以异步方式,我将它作为一条消息而不是两条消息接收,所以它被打印出来

再见

此致, 佩曼·莫尔塔扎维

【问题讨论】:

    标签: c# asynchronous tcp buffer


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 对,现在我在 Send 方法等待 10 毫秒,虽然时间很短,但可以解决问题。并且以自定义格式,我可以理解消息何时开始和结束。
      猜你喜欢
      • 1970-01-01
      • 2023-02-10
      • 1970-01-01
      • 2019-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-17
      相关资源
      最近更新 更多