超高性能套接字服务器 - 实现细节

时间:2011-10-14 21:18:39

标签: c# .net multithreading sockets

我已经完成了我的研究,我知道实现高性能套接字服务器的最佳方法通常如下:使用异步套接字操作(专门的SocketAsyncEventArgs / Operations以获得最佳性能)和异步回调,将请求推送到由线程池提供的处理队列。

我对此处理模型的疑问 - 具有最佳性能:

1)何时应该调用套接字的“结束”操作(例如EndAccept或EndReceive)?应该在排队请求之前在回调线程(IOCP)上调用它吗?或者在从队列中取出请求并进行处理(工作线程)时调用?

2)这个问题取决于#1的答案。什么时候应该调用下一个“开始”操作?我们应该在调用EndOperation之前调用它,还是应该在EndOperation之后立即调用它(在排队/处理请求之前)?

3)处理队列可以只是.NET线程池吗?使用.NET线程池与推出自己的同步处理队列有什么优点/缺点?

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

1)EndReceive应该是你在异步回调中做的第一件事。实际上,在调用EndReceive之前,你不能在回调中做任何其他事情,因为这就是为你提供收到的数据的原因。请参阅Socket.EndReceive上的示例。

同样适用于EndAccept,因为它会为您提供与之通信的套接字。

2)您应该在BeginAccept之后尽快致电EndAccept。否则,如果您的接受回调需要很长时间才能处理,则可能会丢失连接请求。当然,如果你接受回调花了很长时间做任何事情,那你做错了。同样,对于BeginReceive也是如此:在EndRead之后尽快调用它,以避免丢失数据。或者,如果您的通信协议是请求/响应模型,客户端在发送任何更多数据之前需要响应,您可以等到发送响应之后再调用BeginRead

3)处理可以是.NET线程池,但是如果你打算使用它,你应该考虑使用任务并行库。使用TPL的好处在于它非常“火灾和遗忘”,或者可能是“火灾,它会在完成时回叫”。使用TPL的缺点是,您的应用程序更难以了解待处理的任务。如果您创建自己的同步处理队列,您始终知道哪些作业正在等待,并且您有可能检查队列,取消作业等。如果您想使用TPL执行此操作,您最终会创建一组任务,你需要管理,因为no way to get the the list of pending tasks

但如果您不需要查看待处理的任务,那么TPL应该可以正常运行。

这里的相关问题有一些很好的信息。