首页 > 解决方案 > Socket ReceiveAsync、超时和问题

问题描述

我需要为我的一位客户重新实现一些旧cobol数据库的数据库连接驱动程序。应用程序的构建方式,我不能使用async/await(就这样吧,我知道这很愚蠢)。整个应用程序是一个 ASP.NET API。

旧驱动程序使用 c++ dll,它包含在互操作方法中。旧系统背后的想法是:对所有事情都使用一个到数据库的连接,让多个线程发送一个数据包,并让一个线程接收答案并将它们委托给正确的线程。为了保持连接处于活动状态,需要向数据库发送某种 ping 消息并处理其 pong 消息。

我在 c# 中重新实现了 POC,有一个连接,打开一个后台线程并使用 AutoResetEvents 通知正确的线程答案已准备好处理。我将 ReceiveTimeout 设置为 5 秒,虽然没有人向服务器发送数据,但接收超时帮助我将 ping 消息发送到服务器。

重写的一个原因是单连接解决方​​案无法扩展。

所以,我的想法是使用套接字池和ReceiveAsync套接字SocketAsyncEventArgs。该解决方案到目前为止有效,但不是很好。这里有一些问题:

标签: c#multithreadingsocketsiis

解决方案


使用 AutoResetEvents 通知正确的线程答案已准备好处理。

我可以建议一个线程安全的队列吗?BlockingCollection<T>还是BufferBlock<T>

我将 ReceiveTimeout 设置为 5 秒,虽然没有人向服务器发送数据,但接收超时帮助我将 ping 消息发送到服务器。

这很奇怪。我假设整个协议都是基于 ping-pong 的,否则使用接收超时来发送消息将不起作用。

我的想法是在套接字上使用套接字池和带有 SocketAsyncEventArgs 的 ReceiveAsync

如果你不能使用async/ await,我会建议切换到异步 API 的Begin*/End*风格。直接从同步到SocketAsyncEventArgs是一个飞跃;SocketAsyncEventArgs是套接字async编程中最困难的形式。

除了计时器之外还有其他方法可以发送我的 ping 消息吗

我会推荐一个计时器;这是心跳消息的正常解决方案。所需的语义应该是“我们希望至少经常发送数据”。因此,请使用可以在发送常规消息(不接收消息)时重置的计时器。

使用 ReceiveAsync 时,我仍然可以使用普通 Send 发送数据,还是必须使用 SendAsync?

您应该能够对一个流使用同步,对另一个流使用异步。不过,我从未尝试过;我工作过的所有系统都是完全异步的。

当 ReceiveAsync 没有收到所有需要的数据时,我可以使用 Receive 来读取其余数据,还是再次使用 ReceiveAsync 来处理丢失的数据更好?

这个问题对我来说没有多大意义。如果您正在异步读取,则不应阻塞调用线程。

另外,我认为这个问题是从错误的角度提出的。代码似乎想要“接收下一条消息”,但这是从套接字读取的一种有问题的方法。相反,我建议您的代码有一个循环,该循环从套接字中无休止地读取数据并将该数据传递给另一种类型,该类型在必要时对其进行缓冲并在消息完成时推出消息。

这是在负载下调试 IIS 进程时的已知行为吗?

我没想到会这样,但我没有太多 IIS 负载测试经验。


推荐阅读