C套接字客户端/服务器滞后

Kla*_*aus 7 c sockets

我正在编写C/C++客户端/服务器套接字应用程序.此时,客户端每隔50ms将自身连接到服务器并发送消息.

一切似乎都有效,但数据流不是连续的:突然,服务器不再接收任何东西,然后一次收到5条消息......有时候一切正常......

有人知道这种奇怪行为的起源吗?

部分代码:

客户:

while (true)
{
if (SDL_GetTicks()-time>=50)
{
socket = new socket();
socket->write("blah");
message.clear();
message = socket->read();
socket->close();
delete socket;
time=SDL_GetTicks();
}
}
Run Code Online (Sandbox Code Playgroud)

服务器:

while (true) {
fd_set readfs;
struct timeval timeout={0,0};
FD_ZERO(&readfs);
FD_SET(sock, &readfs);
select(sock + 1, &readfs, NULL, NULL, &timeout)
if(FD_ISSET(sock, &readfs))
{
SOCKADDR_IN csin;
socklen_t crecsize = sizeof csin;
SOCKET csock = accept(sock, (SOCKADDR *) &csin, &crecsize);
sock_err = send(csock, buffer, 32, 0);
closesocket(csock);
}
}
Run Code Online (Sandbox Code Playgroud)

编辑: 1.我试着做

int flag = 1;
setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof flag);
Run Code Online (Sandbox Code Playgroud)

在客户端和服务器上,但问题仍然存在.

那些连接/断开是非常有用的,但是当我试着写的时候

socket = new socket();
while (true)
{
if (SDL_GetTicks()-time>=50)
{
socket->write("blah");
message.clear();
message = socket->read();
time=SDL_GetTicks();
}
}
Run Code Online (Sandbox Code Playgroud)

然后消息只发送一次(或收到)......

最后:

我忘了将TCP_NODELAY应用于服务器端的客户端套接字.现在它完美无缺!我将进程放在线程中,以便套接字保持打开状态.谢谢你们 :)

ale*_*rus 9

这就是所谓的" Nagle延迟 ".此算法正在等待TCP堆栈,以便在实际向网络发送任何内容之前到达更多数据,直到某些超时到期为止.所以你应该修改Nagle超时(http://fourier.su/index.php?topic=249.0)或者根本禁用Nagle延迟(http://www.unixguide.net/network/socketfaq/2.16.shtml),所以每次send通话都会发送数据.


Nik*_*sov 5

正如其他人已经回复的那样,您看到的延迟是由于TCP内置的Nagle算法,可以通过设置TCP_NODELAY套接字选项来禁用.

我想指出一下,由于持续的连接和断开连接,您的套接字通信效率非常低.每次客户端连接到服务器时,都会发生三次握手,连接拆除需要四个数据包才能完成.基本上你失去了TCP的大部分好处,但却产生了所有的缺点.

这将是很多更高效地为每个客户端保持服务器持续连接.select(2)或者甚至更好,epoll(4)在Linux上,或kqueue(2)在FreeBSD和Mac上,是在多个套接字上处理IO的非常方便的框架.

  • @Klaus,你需要在双方进行这些改变,而不仅仅是客户.因为服务器在第一次读取后关闭每个连接.此外,TCP不保证对套接字的单个写入对应于另一侧的单个读取.两者通常都是循环完成的.然后您的应用程序协议需要验证收到的字节. (2认同)