套接字ReceiveAsync,超时和问题

时间:2019-02-18 19:01:02

标签: c# multithreading sockets iis

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

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

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

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

因此,我的想法是使用套接字池,并在套接字上使用ReceiveAsyncSocketAsyncEventArgs。 到目前为止,该解决方案仍然有效,但效果不是很好。这里有一些问题:

  • 由于ReceiveTimeout与ReceiveAsync不兼容,是否有其他方法可以使用计时器发送我的ping消息
  • 使用ReceiveAsync时,我是否仍可以使用普通的Send发送数据,还是必须使用SendAsync
  • ReceiveAsync未收到所有必需的数据时,我可以使用Receive来读取其余数据,还是对丢失的数据再次使用ReceiveAsync更好? li>
  • 可能无关紧要:我使用炮兵对新驾驶员进行了一些性能测试;他们不时地在30秒后超时(这是我设置的db-transaction超时);当我尝试调试Artillery时即使没有命中断点也得到ESOCKETTIMEDOUT-在负载下调试IIS进程时,这是已知行为吗?

1 个答案:

答案 0 :(得分:1)

  

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

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

  

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

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

  

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

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

  

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

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

  

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

您应该能够对一个流使用同步,而对另一个流使用异步。我从来没有尝试过;我研究过的所有系统都是完全异步的。

  

当ReceiveAsync未接收到所有必需的数据时,我可以使用Receive读取其余数据,还是对丢失的数据再次使用ReceiveAsync更好?

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

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

  

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

我不希望如此,但是我没有太多的IIS负载测试经验。