C++ TCP套接字发送速度

5
我正在使用简单锁定TCP套接字向远程服务器发送消息,但问题在于每个消息发送所需的时间差异很大。
以下是我得到的一些示例:
Bytes Sent:  217, Time:  34.3336 usec
Bytes Sent:  217, Time:   9.9107 usec
Bytes Sent:  226, Time:  20.1754 usec
Bytes Sent:  226, Time:  38.2271 usec
Bytes Sent:  217, Time:  33.6257 usec
Bytes Sent:  217, Time:  12.7424 usec
Bytes Sent:  217, Time:  21.5912 usec
Bytes Sent:  217, Time:  31.1480 usec
Bytes Sent:  218, Time:  28.3164 usec
Bytes Sent:  218, Time:  13.0963 usec
Bytes Sent:  218, Time:  82.8254 usec
Bytes Sent:  218, Time:  13.0963 usec
Bytes Sent:  227, Time:  30.7941 usec
Bytes Sent:  218, Time:  27.9624 usec
Bytes Sent:  216, Time:   2.1237 usec
Bytes Sent:  218, Time:  12.3884 usec
Bytes Sent:  227, Time:  31.1480 usec
Bytes Sent:  227, Time:  88.4887 usec
Bytes Sent:  218, Time:  93.0901 usec
Bytes Sent:  218, Time:   7.7870 usec
Bytes Sent:  218, Time:  28.3164 usec
Bytes Sent:  227, Time:  89.5505 usec
Bytes Sent:  218, Time:  84.2412 usec
Bytes Sent:  218, Time:  13.8042 usec
Bytes Sent:  227, Time:  99.4612 usec
Bytes Sent:  218, Time:  86.0110 usec
Bytes Sent:  218, Time:  12.3884 usec
Bytes Sent:  218, Time:  87.7807 usec
Bytes Sent:  216, Time:   3.5395 usec
Bytes Sent:  218, Time:   4.6014 usec
Bytes Sent:  218, Time:  36.1034 usec
Bytes Sent:  218, Time:  14.8661 usec
Bytes Sent:  218, Time:  24.0689 usec
Bytes Sent:  218, Time:  18.0517 usec
Bytes Sent:  227, Time:  24.4229 usec

有人知道为什么会发生这种情况吗?为什么一个消息需要3微秒才能被发送,而另一个消息需要80微秒?
是否有任何方法可以修复这个问题?

注意:我想要实现的主要目标是尽可能快地发送每条消息。 我不需要异步套接字,至少在它们工作更快之前不需要。

关于我所做的一些其他细节:

C ++,Visual Studio 2013

我如何打开:

...
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
...
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
...

如何发送和计算时间:

...
LARGE_INTEGER cT;
QueryPerformanceCounter(&cT);
long long dT = cT.QuadPart;

iBytesSent = send(ConnectSocket, msgFinal, msgFinalLen, 0);

QueryPerformanceCounter(&cT);
dT = cT.QuadPart - dT;
...

此外,我正在从另一个线程监听此套接字,我不知道这是否会影响发送:

iResult = recv(ConnectSocket, recvbuf, DEFAULT_BUFLEN, 0);

3
TCP是一种流协议。它没有“消息”概念,您发送的是一个字节流。这意味着接收方可能会以与发送方不同的大小块接收数据。TCP只保证对方按相同顺序接收相同的字节,不会丢失(如果重传失败则会断开连接)。 - hyde
3
我认为你并没有测量发送时间,你只是在测量“send”调用的时间。 - Dariusz
如果您希望尽可能快地发送消息,还可以设置TCP_NODELAY。https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms740476(v=vs.85).aspx - dau_sama
@dau_sama 除非它实际上会使发送过程变慢。当它发送一个数据包时,send操作需要更长的时间。设置TCP_NODELAY将使每个发送操作都发送一个数据包。 - David Schwartz
3个回答

5
你的方法无效。你只是在测量将数据放入发送缓冲区需要多长时间。如果有足够的空间,根本不需要进行网络操作。如果没有足够的空间,则会阻塞直到有足够的空间,这取决于接收者读取已经存在的内容。所以你看到的是有时有空间,有时没有,这取决于接收者是否在读取和跟上。
如果你想测量往返时间,你需要发送一个时间戳并让对等方回显它,然后当你收到它时将其与当前时间进行比较。

有没有办法监控和控制发送的内容以及缓冲区中的内容?也许有一些建议/选项/配置可以指定,使发送过程更快、更稳定?或者如果可能的话,增加缓冲区大小会有所帮助吗? :) - Artem
1
@Artem 有一个简单的方法 - 不要使用TCP。 TCP是一种流协议,如果您尝试将其用于发送快速且小的数据包,则会发现它具有某些保证和缺点,这可能会让您感到烦恼。 UDP可能是更好的选择(尽管您可能希望使用一些高级库来处理此操作)。但请忘记秒。在任何合理的情况下,您仍然需要看一下秒 - 在设计良好的局域网上几乎不可能低于一毫秒,但在互联网上完全是愚蠢的。 - Luaan
@Artem 我已经建议了正确的方法。 缓冲区中有什么或没有什么都是无关紧要的。 - user207421
如果我从终端使用echo命令,性能会差不多吗?这样我就不用编写自己的代码来测试了吧? - Lightsout

1
你并没有测量消息“发送”所需的时间,而是测量了消息进入TCP发送缓冲区所需的时间。这可能涉及内存分配、锁争用和许多其他事情。它还可能包括另一个进程被调度,导致你失去时间片。

1
你所测量的是发送调用所需的时间量。这基本上是在套接字层中向缓冲区进行写入(I/O)操作。
你的进程尝试进行 I/O 并被阻塞 - 一旦 I/O 完成,守护进程就会被唤醒。你在发送调用中看到的时间差包括:
i. 实际写入时间。
ii. 可中断睡眠时间 - 因为调度程序不会在 I/O 完成后立即唤醒你的进程。可能会唤醒另一个进程。
调整:
i. 尝试优化发送/接收窗口大小。这是可以发送而无需等待 ACK 的数据量。
访问:在 C 中设置 TCP 接收窗口并在 Linux 上使用 tcpdump ii. 你传递给发送调用的缓冲区必须适合窗口大小。因此,TCP 不会等待达到最佳大小才实际将数据刷新到网络上。
iii. 类似于 TCP_NODELAY 的标志对你的操作系统实现有所帮助。

iv. 调整守护进程的优先级,以便在阻塞 I/O 调用完成后立即唤醒。


谢谢,我想澄清一点。"iv. 重新调整您的守护程序的优先级值,以便在阻塞I/O调用完成后立即唤醒。"请问“重新调整优先级值”是什么意思,如何进行这种“重新调整”? - Artem
请访问:https://dev59.com/a1vUa4cB1Zd3GeqPxNBU 了解如何引起调度程序的注意。 - Abhinav

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接