我们正在创建一个需要通过TCP / IP套接字与另一个系统通信的c#应用程序。我们希望每秒接收大约1-2个传入事务,每条消息的平均大小约为10k(文本和1个图像)。
然后我们将进行一些处理(可能需要100毫秒到3秒,具体取决于几个变量),然后发回大约1k的响应。
在我看过的例子中,有些是多线程的。对于这个应用程序,将其设置为单线程还是多线程会更好吗?如果建议使用多线程,那么大致不同的线程会做什么?
答案 0 :(得分:5)
(不是特定于C#)
两种方式都做到了(极端性能不是决定因素),我更喜欢每线程1线程的方法。
听众线程
这个线程的工作是在套接字上侦听传入连接,接受它们,并生成一个新的连接线程(给它连接的套接字)。
连接主题
这些线程(每个连接一个)处理与连接套接字的所有通信。如果请求是同步的,它们也可以处理请求的处理(您需要查看特定应用程序的请求)。
当连接断开时,该线程也会死掉。
管理线程
如果需要执行清理或定期维护,这些都可以在自己的线程中运行。
请记住锁定(显然): 连接需要共享多少数据?访问时确保所有资源都已正确锁定,并且您没有任何死锁或竞争条件。然而,这更像是一个“通用线程”主题。
答案 1 :(得分:3)
如果您期望多个连接,则需要多个线程。每个线程都将为特定客户端提供流,它将需要单独处理。
我认为Silverlight policy server是多线程服务器应用程序的第一个很好的例子。但是,它使用Socket类而不是TcpListener。
答案 2 :(得分:2)
我会接受套接字并使用异步调用。允许您接受多个连接,并避免为每个连接创建一个线程。
基本上用监听器
创建一个套接字套接字套接字= tcpListener.AcceptSocket();
和Socket.BeginReceive开始接收数据。
答案 3 :(得分:0)
我认为定义“连接”这个词的含义很重要。
如果其他系统在每次发送事务时都创建了与TcpListener的新连接,那么这将被视为多个连接,并且有一个专用线程来处理这些传入连接请求是有意义的。如果是这种情况,请忽略除此之外的所有内容并使用gahooa的建议解决方案。
另一方面,如果另一个系统只是建立一个连接并通过同一个连接发送所有事务,那么在一个单独的线程中处理连接请求真的没有意义(因为只有一个连接)。如果是这种情况,那么我建议接受一次传入请求并异步读取套接字(而不是轮询套接字以获取数据)。每次收到完整的事务时,将其“挂在墙上”抛给事务处理线程。当处理完成并计算“答案”时,将其“翻过墙”扔到响应线程,该响应线程将结果发送回另一个系统。在这种情况下,基本上有四个线程:
主线程创建TcpListener并等待直到建立连接。此时,它只是启动异步读取并等待程序结束(ManualResetEvent.WaitOne())。
Read线程是为NetworkStream的读取提供服务的异步线程。
Processing线程从Read线程接收事务并执行任何必要的处理。
Write线程接受Processing线程生成的任何响应,并将它们写入NetworkStream。
根据这个link,只要读取和写入在不同的线程中完成,就不必同步读取和写入同一个NetworkStream。您可以使用通用列表或队列在线程之间移动数据。我将为Read-to-Processing数据创建一个,为Processing-to-Write数据创建一个。请确保使用SyncRoot属性同步对它们的访问。