简体   繁体   English

套接字ReceiveAsync,超时和问题

[英]Socket ReceiveAsync, Timeouts and Questions

I need to reimplement a database connection driver for some legacy cobol database for one of my customers. 我需要为我的一位客户的一些旧版cobol数据库重新实现数据库连接驱动程序。 The way the application is built, i cannot use async/await (just leave it like that, i know it is stupid). 应用程序的构建方式,我不能使用async/await (就这样吧,我知道它很愚蠢)。 The whole application is an ASP.NET API. 整个应用程序是一个ASP.NET API。

The old driver uses a c++ dll, that is included with inter-op methods. 旧驱动程序使用c ++ dll,该文件已包含在互操作方法中。 The idea behind the old system is: use one connection to the db for everything, have multiple threads send a packet and have one thread that receives the answers and delegates them to the right thread. 旧系统背后的想法是:使用一个连接到数据库的所有东西,让多个线程发送一个数据包,让一个线程接收答案并将它们委托给正确的线程。 To keep the connection alive, one needs to send some sort of ping message to database and handle its pong message. 为了使连接保持活动状态,需要向数据库发送某种ping消息并处理其pong消息。

I reimplemented that as POC in c#, have one connection, open a background thread and use AutoResetEvents to notify the right threads that the answer is ready to be processed. 我重新实现了,作为c#中的POC,建立一个连接,打开一个后台线程,并使用AutoResetEvents通知正确的线程已经准备好处理该答案。 I set the ReceiveTimeout to 5 seconds, and while there was nobody sending data to the server, the receive timeout helped me to send the ping-message to the server. 我将ReceiveTimeout设置为5秒,虽然没有人向服务器发送数据,但是接收超时帮助我将ping消息发送到服务器。

A reason for the rewrite is, that the one-connection-solution does not scale. 重写的原因是单连接解决方​​案无法扩展。

So, my idea is to use a socket pool and ReceiveAsync with SocketAsyncEventArgs on the sockets. 因此,我的想法是在套接字上使用套接字池和带有SocketAsyncEventArgs ReceiveAsync The solution works so far, but not really good. 到目前为止,该解决方案仍然有效,但效果不是很好。 Here are some questions: 这里有一些问题:

  • As ReceiveTimeout is not compatible with ReceiveAsync , is there a other way then a timer to send my ping-messages 由于ReceiveTimeout与ReceiveAsync不兼容,是否有其他方法可以通过计时器发送我的ping消息
  • when using ReceiveAsync , can i still use normal Send to send data, or do i have to use SendAsync ? 使用ReceiveAsync ,我是否仍可以使用常规的Send发送数据,还是必须使用SendAsync
  • when ReceiveAsync does not receive all required data, may i use Receive to read the rest of it, or is it better to use ReceiveAsync again for the missing data? ReceiveAsync未接收到所有必需的数据时,我可以使用Receive读取其余数据,还是对丢失的数据再次使用ReceiveAsync更好?
  • Maybe not relevant: I use Artillery to fire some performance tests on the new driver; 可能无关紧要:我使用大炮对新驱动程序进行了一些性能测试; from time to time they timeout after 30 seconds (thats the db-transaction timeout i set); 他们不时地在30秒后超时(这是我设置的db-transaction超时); when i try to debug that Artillery gets ESOCKETTIMEDOUT even though no breakpoint is hit - is this a known behaviour when debugging an IIS process under load? 当我尝试调试即使未命中断点时, 炮兵也会获得ESOCKETTIMEDOUT-在负载下调试IIS进程时,这是已知行为吗?

use AutoResetEvents to notify the right threads that the answer is ready to be processed. 使用AutoResetEvents通知正确的线程,该答案已准备好进行处理。

May I suggest a thread-safe queue? 我可以建议一个线程安全队列吗? BlockingCollection<T> or BufferBlock<T> ? BlockingCollection<T>BufferBlock<T>

I set the ReceiveTimeout to 5 seconds, and while there was nobody sending data to the server, the receive timeout helped me to send the ping-message to the server. 我将ReceiveTimeout设置为5秒,虽然没有人向服务器发送数据,但是接收超时帮助我将ping消息发送到服务器。

This is weird. 真奇怪 I assume the entire protocol is ping-pong based, or else using a receive timeout to send messages would not work. 我假设整个协议都是基于ping-pong的,否则使用接收超时发送消息将不起作用。

my idea is to use a socket pool and ReceiveAsync with SocketAsyncEventArgs on the sockets 我的想法是在套接字上使用套接字池和带有SocketAsyncEventArgs的ReceiveAsync

If you can't use async / await , I would advise switching to the Begin* / End* style of asynchronous API. 如果您不能使用async / await ,我建议您切换到异步API的Begin* / End*样式。 Going straight from synchronous to SocketAsyncEventArgs is quite a leap; 从同步直接变为SocketAsyncEventArgs是一个飞跃。 SocketAsyncEventArgs is the most difficult form of socket async programming. SocketAsyncEventArgs是套接字async编程的最困难形式。

is there a other way then a timer to send my ping-messages 还有其他方法可以通过计时器发送我的ping消息

I would recommend a timer; 我建议一个计时器。 that's the normal solution for heartbeat messages. 这是心跳消息的正常解决方案。 The desired semantics should be "we want to send data at least this often". 所需的语义应该是“我们至少要经常发送数据”。 So use a timer that you can reset when sending regular messages (not receiving messages). 因此,请使用可以在发送常规消息(不接收消息)时重置的计时器。

when using ReceiveAsync, can i still use normal Send to send data, or do i have to use SendAsync? 使用ReceiveAsync时,我是否仍可以使用正常的Send发送数据,还是必须使用SendAsync?

You should be able to use synchronous for one stream and asynchronous for the other. 您应该能够对一个流使用同步,而对另一个流使用异步。 I've never tried this, though; 我从来没有尝试过; all systems I've worked on are fully asynchronous. 我研究过的所有系统都是完全异步的。

when ReceiveAsync does not receive all required data, may i use Receive to read the rest of it, or is it better to use ReceiveAsync again for the missing data? 当ReceiveAsync未接收到所有必需的数据时,我可以使用Receive读取其余数据,还是对丢失的数据再次使用ReceiveAsync更好?

This question doesn't make as much sense to me. 这个问题对我来说意义不大。 If you're asynchronously reading, you shouldn't block the calling thread. 如果您正在异步读取,则不应阻塞调用线程。

Also, I think this question is framed from the wrong perspective. 另外,我认为这个问题是从错误的角度提出的。 It seems like the code wants to "receive the next message", but this is a problematic way to approach reading from a socket. 代码似乎想“接收下一条消息”,但这是从套接字读取数据的一种有问题的方式。 Instead, I recommend that your code have a loop that endlessly reads from the socket and passes that data to another type that buffers it as necessary and pushes out messages as they finish. 相反,我建议您的代码具有一个循环,该循环不断地从套接字读取数据,并将该数据传递给另一种类型,该数据在必要时对其进行缓冲,并在完成消息时将其推出。

is this a known behaviour when debugging an IIS process under load? 负载下调试IIS进程时,这是一种已知的行为吗?

I would not expect so, but I don't have much IIS load testing experience. 我不希望如此,但是我没有太多的IIS负载测试经验。

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

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