C++ 接收/发送单线程还是单独线程?

C++ 接收/发送单线程还是单独线程?,c++,tcp,zeromq,C++,Tcp,Zeromq,我在讨论一个客户端应用程序中的多线程时,被告知使用一个单独的线程接收数据,另一个线程发送数据是不可取的 为什么? 据我所知,TCP是全双工的,所以这将是一种性能改进,还是不是?我想这取决于应用程序的规模。如果您正在为一个类项目开发一个小应用程序,那么将发送和接收放在同一个线程上就足够了。这样就不必担心线程问题 然而,我开发的应用程序必须监听数千个传入连接,每个连接可能发送大量数据。我们有一个线程,其唯一目的是监听套接字连接并将新连接放入池中,还有一个数量可变的线程(取决于应用程序的繁忙程度)用于

我在讨论一个客户端应用程序中的多线程时,被告知使用一个单独的线程接收数据,另一个线程发送数据是不可取的

为什么?


据我所知,TCP是全双工的,所以这将是一种性能改进,还是不是?

我想这取决于应用程序的规模。如果您正在为一个类项目开发一个小应用程序,那么将发送和接收放在同一个线程上就足够了。这样就不必担心线程问题

然而,我开发的应用程序必须监听数千个传入连接,每个连接可能发送大量数据。我们有一个线程,其唯一目的是监听套接字连接并将新连接放入池中,还有一个数量可变的线程(取决于应用程序的繁忙程度)用于读取套接字,还有一个不同的线程池用于写入

问题是,如果您的侦听套接字读取数据的速度不够快且缓冲区已满,则会返回一个错误,并且在数千个客户端的情况下,会导致大量重新连接和重新发送数据,这加剧了数据读取速度不够快的问题


因此,回到我在第一个地方所说的——这取决于您的应用程序的规模,但为什么不现在添加这个功能呢?只要确保线程安全,就可以了。

有一个专用的发送线程和一个专用的接收线程是不好的,原因有两个

首先,这意味着每次从接收到发送时都需要进行上下文切换,除非同时进行这两项操作

第二,这意味着在典型的路径中,您接收查询,制定响应,然后发送响应,数据需要从一个线程传递到另一个线程,从而破坏缓存


这就是说,如果性能不是超关键的,并且它很好地适合您的设计,那么它肯定会起作用。只是通常没有优势。

问题是,如果您的侦听套接字读取数据的速度不够快且缓冲区已满,则新传入的数据包将被丢弃-永远丢失。
丢失了吗?怎样?如果绑定到套接字的侦听器工作正常,那么就不存在像
丢弃数据这样的事情,至少在使用TCP时是这样。关于应用程序在套接字上读取的速率不属于您的职责范围,TCP有一个名为
窗口大小
的功能来处理这个问题。“如果绑定到您的套接字的侦听器工作正常”是的,如果侦听器工作正常,您是正确的……但是在数千(10000多)个大型应用程序中对于每个发送兆字节数据的客户端,我看到缓冲区填满了,数据丢失了——我知道有一些数据包是在客户端发送的,但从未发送到服务器上的应用程序。当传入缓冲区已满时,可以丢弃新的传入数据包。也许是服务器端处理不当,但这就是我们所看到的。好吧……下面是我所说的:TCP套接字发回一个错误,这(在客户端应用程序中)导致它丢失数据。Halim,你说得很对,数据丢失不是由于TCP造成的,TCP至少会通知应用程序发生错误,但当数千个应用程序试图重新发送时,它会在应用程序中造成严重问题。糟糕的设计,在几个方面,但线程的阅读有很大帮助。我理解你的观点。但是,如果由于套接字大小不足而丢弃数据包,远程TCP堆栈是否会在以后定期重新发送这些数据包,因为本地堆栈没有正确处理这些数据包?哈利姆,你说得很对,我对答案进行了编辑以澄清。当发送应用程序发送需要原子发送的数据时,问题可能会出现,也就是说,一些数据不够-必须接收所有数据才能使数据有意义,因此发送应用程序出现错误,并试图重新发送数据,这是大量数据,这加剧了问题。是的,存在体系结构错误,如果该公司能够维持足够长的时间,我们甚至可以修复它们。如果您只处理几个套接字,这可能无关紧要,因为无论发生什么情况,您的程序都可能受到I/O限制。如果您计划处理大量客户,这是一篇关于如何高效处理客户的好文章: