gpt4 book ai didi

c# - 使用 SocketAsyncEventArgs 按顺序发送数据

转载 作者:行者123 更新时间:2023-11-30 15:38:16 27 4
gpt4 key购买 nike

我最初在发送数据时遇到了竞争条件,问题是我允许使用多个 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;
}

有道理吗?

关于c# - 使用 SocketAsyncEventArgs 按顺序发送数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11648611/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com