Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用TCPListener类的单线程还是多线程?_C#_Sockets_Tcp - Fatal编程技术网

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

C# 使用TCPListener类的单线程还是多线程?,c#,sockets,tcp,C#,Sockets,Tcp,我们正在创建一个c#应用程序,它需要通过TCP/IP套接字与另一个系统进行通信。我们预计每秒将收到大约1-2个传入事务,每条消息的平均大小约为10k(文本和1个图像) 然后我们将进行一些处理(可能需要100毫秒到3秒不等,具体取决于几个变量),然后返回大约1k的响应 在我看到的示例中,有些是多线程的。对于此应用程序,将其设置为单线程还是多线程更好?如果建议使用多线程,那么不同的线程大致会做什么 如果需要多个连接,则需要多个线程。每个线程都将为特定的客户机提供需要单独处理的流 我认为这是第一次使用

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

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


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

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

我认为这是第一次使用多线程服务器应用程序的好例子。不过,它使用套接字类而不是TcpListener。

(不特定于C)

在这两种方式下(极端性能不是决定因素),我更喜欢每连接一个线程的方法

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

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

当连接失效时,该线程也失效

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

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

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

基本上是用监听器创建一个套接字

Socket-Socket=tcpListener.AcceptSocket()


和Socket.BeginReceive开始接收数据

我认为定义“连接”一词的含义很重要

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

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

  • 主线
  • 读线程
  • 加工线程
  • 写线程
  • 主线程创建TcpListener并等待连接建立。此时,它只是启动异步读取并等待程序结束(ManualResetEvent.WaitOne())

    读取线程是为网络流的读取提供服务的异步线程

    处理线程从读取线程接收事务,并执行任何必要的处理

    写入线程接受处理线程生成的任何响应,并将它们写入NetworkStream


    根据这一点,只要读写在不同的线程中完成,就不必从同一网络流同步读写。您可以使用通用列表或队列在线程之间移动数据。我将创建一个用于读取处理数据,另一个用于处理写入数据。请确保使用SycRooT属性来同步对它们的访问。

    你会说同一个客户端上的同一个端口上的许多连接构成了“多个连接”还是仅仅一个连接?它仍然被认为是多个连接。考虑使用线程池,而不是在每个请求中生成新线程。创建新线程可能代价高昂,并为DOS攻击提供了良好的机会。将有一些共享资源:数据库连接对象、日志对象等。这些通常是线程安全的单例,但我也可以考虑为每个线程提供自己的实例……如果极端性能不是您的主要考虑因素——是什么让您更喜欢多线程?@NagaMensch——在这个给定的例子(Python)中,使用线程要简单得多,因为每个线程都可以进行编码,从而使它相信它是程序中唯一的连接。这也允许使用阻塞套接字。我们使用事件循环+非阻塞套接字编写程序,然后使用线程+阻塞套接字重新编写程序。最好是螺纹。