其他分享
首页 > 其他分享> > SocketAsyncEventArgs按顺序发送数据

SocketAsyncEventArgs按顺序发送数据

作者:互联网

我最初在发送数据时遇到了竞争,问题是我允许使用多个SocketAsyncEventArgs发送数据,但是第一个数据包在第二个数据包之前没有完全发送,这是因为我拥有它,所以如果数据缓冲区不适合缓冲区,直到所有数据发送完毕后循环,并且第一个数据包大于第二个数据包(后者很小),因此第二个数据包已被发送并在第一个数据包之前到达客户端.

我已通过将1 SocketAyncEventArgs分配给用于发送数据的开放连接并使用信号量来限制对其的访问来解决此问题,并在完成后立即进行SocketAsyncEventArgs的回调.

现在可以正常工作,因为已发送所有数据,并在为下一次发送完全准备好时回叫.问题是,当我想将数据随机发送到打开的连接时,以及当有大量数据发送时,它会阻塞我的线程,从而导致阻塞.

我正在寻找解决方法,我想到了一个Queue,当请求发送数据时,它只是将数据包添加到Queue中,然后1个SocketAsyncEventArgs只是循环发送该数据.

但是如何在仍可扩展的同时有效地做到这一点呢?我希望在按照请求发送数据包的顺序发送数据包时,尽量避免阻塞.

感谢任何帮助!

解决方法:

如果数据需要保持秩序,并且您不想阻塞,那么您需要添加一个队列.我这样做的方法是在状态对象上跟踪是否已经为该连接进行了活动的发送异步循环.入队后(显然必须同步),只需检查正在进行的操作即可:

    public void PromptToSend(NetContext context)
    {
        if(Interlocked.CompareExchange(ref writerCount, 1, 0) == 0)
        { // then **we** are the writer
            context.Handler.StartSending(this);
        }
    }

这里writerCount是连接上的写循环数(应为1或0).如果没有,我们开始一个.

我的StartSending尝试从该连接的队列中读取;如果可以,则执行通常的SendAsync等:

if (!connection.Socket.SendAsync(args)) SendCompleted(args);

(请注意,此处的SendCompleted用于“同步”情况;对于“异步”情况,它必须通过事件模型到达SendCompleted).很显然,SendCompleted重复此“出队,尝试发送异步”步骤.

剩下的唯一一件事是确保当我们尝试出队时,如果发现没有其他事情要做,我们会注意到缺乏行动:

        if (bufferedLength == 0)
        {  // nothing to do; report this worker as inactive
            Interlocked.Exchange(ref writerCount, 0);
            return 0;
        }

说得通?

标签:sockets,packets,socketasynceventargs,c,net
来源: https://codeday.me/bug/20191101/1980677.html