我正在编写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();
}
}
服务器:
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);
}
}
编辑:
1。我试着做
int flag = 1;
setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof flag);
在客户端和服务器中,但问题仍然存在。
2.是的,那些连接/断开是非常有用的,但是当我尝试写
时socket = new socket();
while (true)
{
if (SDL_GetTicks()-time>=50)
{
socket->write("blah");
message.clear();
message = socket->read();
time=SDL_GetTicks();
}
}
然后消息只发送一次(或收到)......
最后:
我忘了将TCP_NODELAY应用于服务器端的客户端套接字。现在它完美无缺! 我将进程放在线程中,以便套接字保持打开状态。 谢谢大家:))
答案 0 :(得分:9)
这就是所谓的“Nagle delay”。此算法正在等待TCP堆栈,以便在实际向网络发送任何内容之前到达更多数据,直到某些超时到期为止。因此,您应该修改Nagle超时(http://fourier.su/index.php?topic=249.0)或完全禁用Nagle延迟(http://www.unixguide.net/network/socketfaq/2.16.shtml),以便按send
调用发送数据。
答案 1 :(得分:5)
正如其他人已经回复的那样,您看到的延迟是由于TCP内置Nagle algorithm造成的,可以通过设置TCP_NODELAY
套接字选项来禁用。
我想指出,由于持续的连接和断开连接,您的套接字通信效率非常低。每次客户端连接到服务器时都会发生three way handshake,连接拆除需要四个数据包才能完成。基本上你失去了TCP的大部分好处,但却产生了所有的缺点。
每个客户端维护与服务器的持久连接会更加高效。 更高效。 select(2)
,甚至更好,Linux上的epoll(4)
或FreeBSD和Mac上的kqueue(2)
,是在多个套接字上处理IO的非常方便的框架。
答案 2 :(得分:3)
您可以使用TCP_NODELAY套接字选项立即强制发送数据。