C# 使用TCPListener类的单线程还是多线程?
我们正在创建一个c#应用程序,它需要通过TCP/IP套接字与另一个系统进行通信。我们预计每秒将收到大约1-2个传入事务,每条消息的平均大小约为10k(文本和1个图像) 然后我们将进行一些处理(可能需要100毫秒到3秒不等,具体取决于几个变量),然后返回大约1k的响应C# 使用TCPListener类的单线程还是多线程?,c#,sockets,tcp,C#,Sockets,Tcp,我们正在创建一个c#应用程序,它需要通过TCP/IP套接字与另一个系统进行通信。我们预计每秒将收到大约1-2个传入事务,每条消息的平均大小约为10k(文本和1个图像) 然后我们将进行一些处理(可能需要100毫秒到3秒不等,具体取决于几个变量),然后返回大约1k的响应 在我看到的示例中,有些是多线程的。对于此应用程序,将其设置为单线程还是多线程更好?如果建议使用多线程,那么不同的线程大致会做什么 如果需要多个连接,则需要多个线程。每个线程都将为特定的客户机提供需要单独处理的流 我认为这是第一次使用
在我看到的示例中,有些是多线程的。对于此应用程序,将其设置为单线程还是多线程更好?如果建议使用多线程,那么不同的线程大致会做什么 如果需要多个连接,则需要多个线程。每个线程都将为特定的客户机提供需要单独处理的流 我认为这是第一次使用多线程服务器应用程序的好例子。不过,它使用套接字类而不是TcpListener。(不特定于C) 在这两种方式下(极端性能不是决定因素),我更喜欢每连接一个线程的方法 侦听器线程
这个线程的工作是监听套接字上的传入连接,接受它们,并生成一个新的连接线程(给它连接的套接字) 连接线程
这些线程(每个连接一个)处理与连接的套接字的所有通信。如果请求是同步的,它们还可以处理请求的处理(您需要为您的特定应用程序研究这一点) 当连接失效时,该线程也失效 管理线程
如果需要执行清理或定期维护,这些都可以在自己的线程中运行 记住锁定(显然):
连接需要共享多少数据?确保在访问时正确锁定了所有资源,并且没有任何死锁或竞争条件。不过,这更像是一个“常规线程”主题。我会接受套接字并使用异步调用。允许您接受多个连接,并避免为每个连接创建线程 基本上是用监听器创建一个套接字 Socket-Socket=tcpListener.AcceptSocket()
和Socket.BeginReceive开始接收数据 我认为定义“连接”一词的含义很重要 如果另一个系统在每次发送事务时都创建到您的TcpListener的新连接,那么这将被视为多个连接,并且有一个专用线程来处理这些传入的连接请求是有意义的。如果是这种情况,请忽略除此之外的所有内容,并使用gahooa的建议解决方案 另一方面,如果另一个系统只是建立一个连接并通过该连接发送所有事务,那么在单独的线程中处理连接请求就没有意义了(因为只有一个连接)。如果是这种情况,那么我建议接受传入请求一次并异步读取套接字(而不是轮询套接字以获取数据)。每次收到一个完整的事务时,都将其“扔到墙上”到事务处理线程。当处理完成并计算“答案”时,将其“扔到墙外”到响应线程,该线程将结果发送回另一个系统。在此场景中,基本上有四个线程:
根据这一点,只要读写在不同的线程中完成,就不必从同一网络流同步读写。您可以使用通用列表或队列在线程之间移动数据。我将创建一个用于读取处理数据,另一个用于处理写入数据。请确保使用SycRooT属性来同步对它们的访问。你会说同一个客户端上的同一个端口上的许多连接构成了“多个连接”还是仅仅一个连接?它仍然被认为是多个连接。考虑使用线程池,而不是在每个请求中生成新线程。创建新线程可能代价高昂,并为DOS攻击提供了良好的机会。将有一些共享资源:数据库连接对象、日志对象等。这些通常是线程安全的单例,但我也可以考虑为每个线程提供自己的实例……如果极端性能不是您的主要考虑因素——是什么让您更喜欢多线程?@NagaMensch——在这个给定的例子(Python)中,使用线程要简单得多,因为每个线程都可以进行编码,从而使它相信它是程序中唯一的连接。这也允许使用阻塞套接字。我们使用事件循环+非阻塞套接字编写程序,然后使用线程+阻塞套接字重新编写程序。最好是螺纹。