繁体   English   中英

使用SocketAsyncEventArgs按顺序发送数据

[英]Sending data in order with SocketAsyncEventArgs

我最初在发送数据时遇到了竞争条件,问题是我允许多个SocketAsyncEventArgs用于发送数据,但是第一个数据包在第二个数据包之前没有完全发送,这是因为我有这样的数据,如果数据在发送所有数据之前,它不适合它循环的缓冲区,并且第一个数据包大于第二个数据包很小,因此第二个数据包在第一个数据包之前被发送并到达客户端。

我通过将1个SocketAyncEventArgs分配给用于发送数据的开放连接并使用信号量来限制对它的访问来解决这个问题,并在完成后使SocketAsyncEventArgs回调。

现在这样可以正常工作,因为所有数据都已发送,当它完全准备好下次发送时回调。 这个问题是,当我想要随机地向开放连接发送数据时,它会导致阻塞,并且当有大量数据发送时它会阻塞我的线程。

我正在寻找一个解决这个问题的工作,我想到了一个队列,当请求发送数据时,它只是将数据包添加到队列中,然后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;
        }

合理?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM