套接字

时间:2018-02-17 03:44:50

标签: c# multithreading sockets io

我想在套接字处于活动状态时不断收到并同时从不同的线程调用send方法(对不起我的英文)。

我考虑过以下几点:

  • 由于会有多个客户端,我认为如果操作系统负责生成线程以免损害性能会更好,因此,我不想在循环中检查Receive方法在每个客户端的不同线程上。我立即放弃了。

  • 为了避免创建实现每次调用BeginReceive时使用的IAsyncResult接口的类型的实例,因此不会对GB施加压力,并且在IO操作负载过重时具有更好的性能我决定不使用BeginReceive / EndReceive。

  • 相反,我考虑过为每个连接使用ReceiveAsync方法和可重用的SocketAsyncEventArgs实例。例如,如果服务器支持1000个连接,则它将具有相同数量的SocketAsyncEventArgs实例,在连接处于活动状态期间,每个客户端一个实例。当客户端断开底层SocketAsyncEventArgs时,实例将返回池以供以后在另一个连接中使用(解决方案选择)

  • 关于发送操作,我不关心发送请求是否按呼叫顺序处理;重要的是字节不与其他消息的字节混合,因此在远程主机的接收缓冲区中,消息一个接一个地到达,以便负责协议的类可以解释它们。 / p>

  • 为此,我不想调用BeginSend / EndSend,因为除了在每次调用中创建不同的IAsynResult实例之外,我理解在从不同的线程调用时,消息字节可能是混合的,这是正确的?我不记得很久以前我在哪里读过它。我想有可靠的消息来源。无论是否真实,我都不打算使用它。

  • 我也理解SendAsync就像是BeginSend / EndSend的掩码,不同之处在于它重用了底层的IAsyncResult实例。这让我觉得虽然我可以同时调用SendAsyn方法和BeginSend,但也有可能在输出缓冲区中混合字节。

  • 要使用SendAsyn处理多个调用,您还应该在每次调用时提供不同的SocketAsyncEventArgs实例,这是我不喜欢的。然后我考虑使用Semaphore类来保证一次发送操作,一旦完成,重用上一次发送操作中使用的SocketAsyncEventArgs实例。这样我每个连接只会占用两个SocketAsyncEventArgs实例(一个接收,一个接收),我避免使用这些对象的池,不仅如此,它还可以防止不同消息的字节在输出中混合缓冲液中。

  • 关于我发现不断收到的解决方案,我很满意。但对于运输业务,我不确定。使用SendAsync时,我没有发现任何优势。我只想要多个线程可以同时调用送货方式。然后我考虑使用Send方法并将其包装在异步方法中,如下所示:

    public virtual async Task<int> SendAsync(byte[] buffer, int offset, int size, CancellationToken cancellationToken)
    {
        ThrowIfDisposed();
    
        var sendingRequest = CancellationTokenSource.CreateLinkedTokenSource(requests.Token, cancellationToken);
    
        int bytesSent = 0;
    
        try
        {
            await semaphore.WaitAsync(sendingRequest.Token).ConfigureAwait();
    
            while(bytesSent < size)
            {
                int bytesWrote = clientSocket.Send(buffer, offset, size, SocketFlags.None);
    
                if(bytesWrote == 0)
                {
                    throw new SocketException((int)SocketError.NotConnected);
                }
                else
                {
                    bytesSend += bytesWrote;
                }
            }
         }
         catch(SocketException)
         {
             Disconnect();
    
             throw;
         }
         finally
         {
             semaphore.Release();
    
             sendingRequest.Dispose();
             sendingRequest = null;
         }
    
         return bytesSent;
    } 
    

如果你告诉我上面说的所有内容我错了,或者我的方法是否正确,或者如何改进我已有的内容,我将不胜感激。

感谢。

0 个答案:

没有答案