c# - Socket ReceiveAsync、超时和问题
问题描述
我需要为我的一位客户重新实现一些旧cobol
数据库的数据库连接驱动程序。应用程序的构建方式,我不能使用async/await
(就这样吧,我知道这很愚蠢)。整个应用程序是一个 ASP.NET API。
旧驱动程序使用 c++ dll,它包含在互操作方法中。旧系统背后的想法是:对所有事情都使用一个到数据库的连接,让多个线程发送一个数据包,并让一个线程接收答案并将它们委托给正确的线程。为了保持连接处于活动状态,需要向数据库发送某种 ping 消息并处理其 pong 消息。
我在 c# 中重新实现了 POC,有一个连接,打开一个后台线程并使用 AutoResetEvents 通知正确的线程答案已准备好处理。我将 ReceiveTimeout 设置为 5 秒,虽然没有人向服务器发送数据,但接收超时帮助我将 ping 消息发送到服务器。
重写的一个原因是单连接解决方案无法扩展。
所以,我的想法是使用套接字池和ReceiveAsync
套接字SocketAsyncEventArgs
。该解决方案到目前为止有效,但不是很好。这里有一些问题:
- 由于 ReceiveTimeout 不兼容
ReceiveAsync
,有没有其他方法,然后是一个计时器来发送我的 ping 消息 - 使用的时候
ReceiveAsync
,我还能用普通Send
的发送数据吗,还是必须使用SendAsync
? - 当
ReceiveAsync
没有收到所有需要的数据时,我可以用Receive
它来读取其余部分,还是最好ReceiveAsync
再次使用丢失的数据? - 也许不相关:我使用 Artillery 对新驱动程序进行一些性能测试;他们有时会在 30 秒后超时(这是我设置的数据库事务超时);当我尝试调试即使没有命中断点, Artillery也会获得 ESOCKETTIMEDOUT - 这是在负载下调试 IIS 进程时的已知行为吗?
解决方案
使用 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 负载测试经验。
推荐阅读
- laravel - 我如何通过 Category::all(); 到每一个视图
- talend - Talend Automation 工作耗时过长
- javascript - 如何将 JSON 数组对象放入 Bootstrap 表?
- reactjs - 我可以使用 useRef 将对元素的引用传递给孩子吗?
- kubernetes - 来自 kubernetes 主机的 DNS 解析
- xml - XML 是否有“一个模式规则”?
- java - 为什么 Java 不能推断类型?
- java - AWS Cognito 用户设备触发器
- trains - 火车:我可以重置任务的状态吗?(从“中止”回到“正在运行”)
- javascript - DAC银行贷款自动化