【发布时间】:2014-01-07 17:12:32
【问题描述】:
我有一个 C# 应用程序,它侦听传入的 TCP 连接并从以前接受的连接接收数据。请帮助我是否使用线程池或异步方法来编写程序?注意,一旦一个连接被接受,它并不会关闭它,而是不断地从这个连接接收数据,同时它接受更多的连接
【问题讨论】:
标签: c# asynchronous tcp threadpool
我有一个 C# 应用程序,它侦听传入的 TCP 连接并从以前接受的连接接收数据。请帮助我是否使用线程池或异步方法来编写程序?注意,一旦一个连接被接受,它并不会关闭它,而是不断地从这个连接接收数据,同时它接受更多的连接
【问题讨论】:
标签: c# asynchronous tcp threadpool
线程池线程在代码花费不到半秒且不会阻塞线程的大量 I/O 时工作得最好。这与您描述的情况完全相反。
这里强烈指出使用 Socket.BeginReceive()。在操作级别和框架上都进行了高度优化,您的程序使用单个线程等待 所有 挂起的读取完成。扩展以处理数千个活动连接是非常可行的。
干净地编写异步代码可能非常困难,您通常在线程池线程上运行的方法中将局部变量设为局部变量的变量会变成类的字段。您需要一个状态机来跟踪连接状态。您将从 C# 版本 5 中提供的 async/await 支持中受益匪浅,它允许您将这些状态变量转换回局部变量。您在 this answer 或 this blog post 中找到的小包装器将有很大帮助。
【讨论】:
这主要取决于你想对你的连接做什么。如果您有未知数量的连接,您不知道它们会打开多长时间,我认为最好使用异步调用。
但如果你至少知道平均值。连接数和连接是短期连接,例如 Web 服务器的连接,那么最好使用线程池来完成,因为您不会浪费时间为每个套接字创建线程。
【讨论】:
首先,如果可能,请不要使用 TCP/IP。我建议您自行托管 WebAPI 和/或 SignalR。但如果你决定使用 TCP/IP...
您应该始终对套接字使用异步 API。理想情况下,您希望不断地从套接字读取并定期写入(保持活动消息,如果没有别的)。您不想想要做的是有时间只用于阅读(例如,等待下一条消息),或者有时间用于您只用于写作(例如,发送消息) .当你阅读时,你应该定期写作;当你写作的时候,你应该不断地阅读。
这可以帮助您检测半开连接,也可以避免死锁。
您可能会发现我的TCP/IP .NET Sockets FAQ 很有帮助。
【讨论】:
肯定使用asynchronous 套接字...阻塞等待IO 的线程绝不是一个好主意。
如果您确定自己有高性能需求,您应该考虑为您的套接字使用EAP 设计模式。
这将允许您创建具有较低内存配置文件的异步解决方案。然而,有些人发现使用带有套接字的事件很尴尬而且有点笨拙......如果你属于这一类,你可以看看这篇博客文章来使用 .NET 4.5 的 async/await 关键字:@987654321 @
【讨论】: