使用TCPListener类的单线程还是多线程?

时间:2009-08-10 20:50:36

标签: c# sockets tcp

我们正在创建一个需要通过TCP / IP套接字与另一个系统通信的c#应用程序。我们希望每秒接收大约1-2个传入事务,每条消息的平均大小约为10k(文本和1个图像)。

然后我们将进行一些处理(可能需要100毫秒到3秒,具体取决于几个变量),然后发回大约1k的响应。

在我看过的例子中,有些是多线程的。对于这个应用程序,将其设置为单线程还是多线程会更好吗?如果建议使用多线程,那么大致不同的线程会做什么?

4 个答案:

答案 0 :(得分:5)

(不是特定于C#)

两种方式都做到了(极端性能不是决定因素),我更喜欢每线程1线程的方法。

听众线程
这个线程的工作是在套接字上侦听传入连接,接受它们,并生成一个新的连接线程(给它连接的套接字)。

连接主题
这些线程(每个连接一个)处理与连接套接字的所有通信。如果请求是同步的,它们也可以处理请求的处理(您需要查看特定应用程序的请求)。

当连接断开时,该线程也会死掉。

管理线程
如果需要执行清理或定期维护,这些都可以在自己的线程中运行。

请记住锁定(显然): 连接需要共享多少数据?访问时确保所有资源都已正确锁定,并且您没有任何死锁或竞争条件。然而,这更像是一个“通用线程”主题。

答案 1 :(得分:3)

如果您期望多个连接,则需要多个线程。每个线程都将为特定客户端提供流,它将需要单独处理。

我认为Silverlight policy server是多线程服务器应用程序的第一个很好的例子。但是,它使用Socket类而不是TcpListener。

答案 2 :(得分:2)

我会接受套接字并使用异步调用。允许您接受多个连接,并避免为每个连接创建一个线程。

基本上用监听器

创建一个套接字

套接字套接字= tcpListener.AcceptSocket();

和Socket.BeginReceive开始接收数据。

答案 3 :(得分:0)

我认为定义“连接”这个词的含义很重要。

如果其他系统在每次发送事务时都创建了与TcpListener的新连接,那么这将被视为多个连接,并且有一个专用线程来处理这些传入连接请求是有意义的。如果是这种情况,请忽略除此之外的所有内容并使用gahooa的建议解决方案。

另一方面,如果另一个系统只是建立一个连接并通过同一个连接发送所有事务,那么在一个单独的线程中处理连接请求真的没有意义(因为只有一个连接)。如果是这种情况,那么我建议接受一次传入请求并异步读取套接字(而不是轮询套接字以获取数据)。每次收到完整的事务时,将其“挂在墙上”抛给事务处理线程。当处理完成并计算“答案”时,将其“翻过墙”扔到响应线程,该响应线程将结果发送回另一个系统。在这种情况下,基本上有四个线程:

  1. 主线
  2. 阅读帖子
  3. 处理线程
  4. 写线程
  5. 主线程创建TcpListener并等待直到建立连接。此时,它只是启动异步读取并等待程序结束(ManualResetEvent.WaitOne())。

    Read线程是为NetworkStream的读取提供服务的异步线程。

    Processing线程从Read线程接收事务并执行任何必要的处理。

    Write线程接受Processing线程生成的任何响应,并将它们写入NetworkStream。

    根据这个link,只要读取和写入在不同的线程中完成,就不必同步读取和写入同一个NetworkStream。您可以使用通用列表或队列在线程之间移动数据。我将为Read-to-Processing数据创建一个,为Processing-to-Write数据创建一个。请确保使用SyncRoot属性同步对它们的访问。