我正在使用C#的异步套接字,并使用BeginReceive从套接字读取数据到8192字节的byte []-Buffer。但是,当再次调用BeginReceive之前有新的数据包出现时,会发生什么呢?我当前的设置在停止之前会处理大约3条传入消息。我假设Socket必须先将传入的数据存储在某处,然后BeginReceive才能对其进行处理。

我是否可以控制Socket停止之前缓冲多少数据?

我是否必须足够快地处理传入消息以免“遗漏”任何消息?

如果以下示例中的ProcessMessageBuffer方法花费了很长时间(由于某种原因)而导致传入的数据开始堆积在Socket中时,会发生什么情况?

public void ReadCallback(IAsyncResult ar)
    {
        // We have a new TCP Packet!
        int bytesReceived = 0;

        try
        {
            // The amount of bytes we have just received
            bytesReceived = Socket.EndReceive(ar);
        }
        catch (SocketException ex)
        {
            // The client closed the connection
            OnSocketException(new SocketExceptionEventArgs(ex));
        }

        if (bytesReceived > 0)
        {
            // We have received some data. Write it to the MessageBuffer
            MessageBuffer.Write(ReceiveBuffer, 0, bytesReceived);

            // Process the Messages that may be stored in the MessageBuffer
            // What happens, if this takes too long?
            ProcessMessageBuffer(MessageBuffer.ToArray());

            // Get ready to receive more data
            Socket.BeginReceive(ReceiveBuffer, 0, ReceiveBuffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), null);
        }
    }

最佳答案

网络I/O会在每个步骤中进行缓冲。因此,很难知道您担心哪个“缓冲区”。

Socket.ReceiveBufferSize :



根据您的问题:



您至少可以使用以下几种策略:

  • 修改ReceiveBufferSize属性值。这将更改套接字对象中缓冲区的大小。
  • 在对BeginReceive()的调用中使用更大的缓冲区。这将为Socket对象提供更多空间,可以在不再清空自己的缓冲区之前将其写入其中。请注意,传递给Socket的缓冲区将固定,直到接收操作完成,这可能会影响内存堆管理。
  • 发出多个BeginReceive()调用。这与提供更大的缓冲区具有相似的效果,但是使您可以更精细地控制缓冲区。随之而来的是复杂性,由于Windows如何安排线程,您可能最终以与最初调用BeginReceive()的顺序不同的顺序执行接收操作完成的回调。数据将按照BeginReceive()调用的顺序以及您传递的每个缓冲区的顺序排列正确,但这些缓冲区可能会在您的代码中出现,以使其顺序困惑(它们不是真正的,但是稍后处理该线程的线程填充的缓冲区可能会在线程处理较早填充的缓冲区之前运行)。

  • 有关其他更多信息,请参见socket buffer size: pros and cons of bigger vs smaller



    否。TCP是可靠的。如果您没有足够快地处理数据,则所有事情都会发生,即远程端点将不得不等待发送更多数据。

    也就是说,您应该非常努力地使套接字I/O代码尽快运行。如果您有一些处理速度足够慢以延迟接收操作,则应将该处理任务卸载到一个完全独立的线程中,自己缓冲接收到的数据(例如,使用MemoryStreamFileStream,某种队列等)。

    如果这样做,那么除了简单,默认的套接字处理之外,您将无需执行任何其他操作。您将能够一次拥有一个未完成的BeginReceive(),无需调整套接字的缓冲区,并且能够分配“普通大小”的byte[]对象(或保留一个用于重复使用) 。

    关于c# - C#异步套接字: How much data does the Socket store when the call to BeginReceive is delayed?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43433745/

    10-09 06:45