多个线程和阻塞套接字

时间:2011-02-22 20:22:18

标签: c++ windows multithreading sockets

我正在Windows Server 2k8上编写TCP服务器。此服务器接收数据,对其进行解析,然后将其接收到数据库中。我现在正在做一些测试,但结果令我惊讶。

应用程序是用C ++编写的,直接使用Winsocks和Windows API。它为每个客户端连接创建一个线程。对于每个客户端,它读取并解析数据,然后将其插入数据库。

客户端始终以同时块的形式连接 - 即。每隔一段时间约5(我控制此参数)客户端将同时连接并向服务器提供数据。

我一直在计算每个线程的读取和解析以及与数据库相关的阶段。

第一阶段(阅读和解析)有一种奇怪的行为。每个线程所花费的时间大致等于每个线程,但也与连接的线程数成比例。服务器 CPU缺乏:它有8个核心,并且总是少于8个线程连接到它。

例如,对于3个同步线程,将在大约4,5s内读取和解析100k行(对于每个线程)。但是有5个线程,平均需要9,1s!

我的一位朋友表示,这种扩展行为可能与我正在使用阻塞套接字的事实有关。这是正确的吗?如果没有,这可能是什么原因?

如果是的话,如果有人能指出我在Windows上理解非阻塞套接字的良好资源,我会很高兴。

修改

每个客户端线程从套接字读取一行(即,所有字符直到'\ n'),然后解析它,然后再次读取,直到解析失败或找到终止符。我的readline例程基于:

http://www.cis.temple.edu/~ingargio/cis307/readings/snaderlib/readline.c

将静态变量声明为__declspec(thread)。

从非网络版本开始,解析是有效的(对于100k行,大约为2s)。因此我认为问题出现在多线程/网络版本中。

5 个答案:

答案 0 :(得分:4)

如果您的行长度大约为120-150个字符,那么您实际上使网络饱和!

套接字没有问题。简单地在100 Mbps线路上传输3次100k线路,每个线路150个字节(1个占用10个字节/字节来计算接头)将需要... 4.5 s!套接字,阻塞或其他方面没有问题。您只需达到可以提供多少数据的限制。

答案 1 :(得分:0)

要记住的一件事是,虽然每个客户端有一个线程,但Windows不会自动确保它们都在不同的核心上运行。如果其中一些运行在同一个核心上,则可能(尽管不太可能)使您的服务器处于某种CPU缺乏状态,其中一些核心处于100%负载而其他核心处于空闲状态。对于操作系统如何分散负载(在默认情况下),根本无法保证。

要明确地将线程分配给特定核心,您可以使用SetThreadAffinityMask。可能会或者可能不值得花一点时间来看看它是否有帮助。

另一方面,这个可能根本没有任何关系。 YMMV。

答案 2 :(得分:0)

非阻塞套接字仅在您希望一个线程为多个连接提供服务时才有用。使用非阻塞套接字和轮询/选择循环意味着您的线程在等待新连接时不会处于空闲状态。

在您的情况下,这不是问题,因为每个线程只有一个连接,所以如果您的线程正在等待输入,则没有问题。

这会导致您最初的问题,即当您有更多关联时,事情会变慢。没有进一步的信息,最可能的罪魁祸首是您的网络受限:即您的网络无法足够快地提供服务器数据。

如果您对Windows上的非阻塞套接字感兴趣,请在MSDN上搜索OVERLAPPED API

答案 3 :(得分:0)

除了阻止与非阻止之外,您可能还想研究微软的overlapped I/O。 Google是您的朋友,但在搜索字词中使用overlapped I/O

有关该主题的一般背景信息,请访问Socket overlapped I/O versus blocking/nonblocking mode。本文区分了阻塞/非阻塞和重叠I / O这两个概念。

过去,我使用非阻塞模式的套接字和重叠的I / O.

我真的无法对您的特定扩展问题进行真正的诊断,但如果您能帮助它,应该避免阻塞。

MSDN在记录阻止/非阻止模式以及overlapped I/O API Overlapped I/O and Event Objects方面做得相当不错。

答案 4 :(得分:0)

您可能遇到其他与线程相关的问题,例如死锁/竞争条件/虚假共享,这可能会破坏性能。

相关问题