Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步套接字:当对BeginReceive的调用延迟时,套接字存储了多少数据?_C#_Sockets_Networking_Tcp - Fatal编程技术网

C# 异步套接字:当对BeginReceive的调用延迟时,套接字存储了多少数据?

C# 异步套接字:当对BeginReceive的调用延迟时,套接字存储了多少数据?,c#,sockets,networking,tcp,C#,Sockets,Networking,Tcp,我使用C#的异步套接字,并使用BeginReceive将数据从套接字读取到8192字节的字节[]-缓冲区中。但是,当新数据包在再次调用BeginReceive之前传入时,会发生什么呢?我当前的设置在停止前处理大约3条传入消息。我假设套接字必须在BeginReceive处理传入数据之前将其存储在某个位置 我可以控制套接字在停止之前缓冲多少数据吗 我是否必须依靠足够快的速度来处理传入的消息,以避免“错过”任何消息 当下面示例中的ProcessMessageBuffer方法花费很长时间(出于某种原因)

我使用C#的异步套接字,并使用BeginReceive将数据从套接字读取到8192字节的字节[]-缓冲区中。但是,当新数据包在再次调用BeginReceive之前传入时,会发生什么呢?我当前的设置在停止前处理大约3条传入消息。我假设套接字必须在BeginReceive处理传入数据之前将其存储在某个位置

我可以控制套接字在停止之前缓冲多少数据吗

我是否必须依靠足够快的速度来处理传入的消息,以避免“错过”任何消息

当下面示例中的ProcessMessageBuffer方法花费很长时间(出于某种原因)导致传入数据开始堆积在套接字中时,会发生什么情况

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在该过程的每一步都会进行缓冲。所以很难知道你在担心哪个“缓冲区”

发件人:

…默认值为8192。

较大的缓冲区大小可能会减少空确认(没有数据部分的TCP数据包)的数量,但也可能会延迟对连接困难的识别。如果您正在传输大文件,或者使用高带宽、高延迟连接(例如卫星宽带提供商),请考虑增加缓冲区大小。 根据你的问题:

我可以控制套接字在停止之前缓冲多少数据吗

您至少有几种可用的策略:

  • 修改
    ReceiveBufferSize
    属性值。这将更改套接字对象中缓冲区的大小
  • 在对
    BeginReceive()
    的调用中使用更大的缓冲区。这将为
    Socket
    对象提供更多的空间,使其能够在不再清空自己的缓冲区之前写入。请注意,传递给套接字的缓冲区将被固定,直到接收操作完成,这可能会影响内存堆管理
  • 发出多个
    BeginReceive()
    调用。这与提供更大的缓冲区具有类似的效果,但可以让您对缓冲区进行更细粒度的控制。它带来的复杂性是,由于Windows如何调度线程,您可能会以不同于您最初调用的
    BeginReceive()
    的顺序执行接收操作完成的回调。根据
    BeginReceive()
    调用的顺序和您传递的每个缓冲区,数据的顺序将是正确的,但是这些缓冲区在代码看来可能是无序填充的(它们不是真的,但是处理稍后填充的缓冲区的线程可能会在处理先前填充的缓冲区的线程之前运行)
有关更多详细信息,请参阅

我是否必须依靠足够快的速度来处理传入的消息,以避免“错过”任何消息

不,TCP是可靠的。如果处理数据的速度不够快,那么远程端点将不得不等待发送更多数据

也就是说,您应该非常努力地使套接字I/O代码尽快工作。如果某些处理速度慢到足以延迟接收操作,则应将该处理卸载到完全独立的线程,自己缓冲接收到的数据(例如,使用
内存流
文件流
、某种队列等)


如果您这样做,那么除了简单的默认套接字处理之外,您可能不需要做任何事情。您将能够立即拥有一个突出的
BeginReceive()
,您不必调整套接字的缓冲区,并且您将能够分配“正常大小的”
byte[]
对象(或者保留一个以备重用)。

网络I/O在每一步都会被缓冲。所以很难知道你在担心哪个“缓冲区”

发件人:

…默认值为8192。

较大的缓冲区大小可能会减少空确认(没有数据部分的TCP数据包)的数量,但也可能会延迟对连接困难的识别。如果您正在传输大文件,或者使用高带宽、高延迟连接(例如卫星宽带提供商),请考虑增加缓冲区大小。 根据你的问题:

我可以控制套接字在停止之前缓冲多少数据吗

您至少有几种可用的策略:

  • 修改
    ReceiveBufferSize
    属性值。这将更改套接字对象中缓冲区的大小
  • 在对
    BeginReceive()
    的调用中使用更大的缓冲区。这将为
    Socket
    对象提供更多的空间,使其能够在不再清空自己的缓冲区之前写入。请注意,传递给套接字的缓冲区将被固定,直到接收操作完成,这可能会影响内存堆管理
  • 发出多个
    BeginReceive()
    调用。这与提供更大的缓冲区具有类似的效果,但可以让您对缓冲区进行更细粒度的控制。它带来的复杂性是,由于Windows如何调度线程,您可能会以不同于您最初调用的
    BeginReceive()
    的顺序执行接收操作完成的回调。根据
    BeginReceive()
    调用的顺序和您传递的每个缓冲区,数据的顺序将是正确的,但是这些缓冲区在代码看来可能是无序填充的(它们不是真的,但是处理稍后填充的缓冲区的线程可能会在处理先前填充的缓冲区的线程之前运行)
有关更多详细信息,请参阅

我是否必须依靠足够快的速度来处理传入的消息,以避免“错过”任何消息

不,TCP是可靠的。如果你处理数据的速度不够快,所有这些都会发生