【发布时间】:2014-03-23 11:13:48
【问题描述】:
我的 TCP 服务器的数据包传输延迟增加似乎存在问题。现在,该服务器必须是 TCP,因为 UDP 被防火墙阻止(这是一种客户端-服务器-客户端类型的通信)。我也知道像我一样发送带有浮点整数的结构是非常不可移植的,但是,在可预见的将来,该系统将运行 Windows 客户端到 Windows 服务器到 Windows 客户端。
问题是这样的:客户端开始从另一个客户端正确接收数据,但是,延迟会呈指数级恶化(大约 3 分钟后,数据包落后了近 30 秒 - 但正确,当他们到达时)。我研究了它并在 Microsoft 页面上找到了一个答案,解释它是由于完整的发送缓冲区,但是,它们的 setsockopt 语法与记录的示例不匹配,所以也许我错了。
无论如何,任何建议都将不胜感激:
服务器相关部分:
(当 accept() 被调用时:)
int buff_size = 2048000;
int nodel = 1;
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&buff_size, sizeof(int));
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&buff_size, sizeof(int));
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&nodel, sizeof(nodel));
消息重定向循环:
if (gp->curr_pilot < sz && gp->users[gp->curr_pilot].pilot == TRUE) {
char* pbuf = new char[1024];
int recvd = recv(gp->users[gp->curr_pilot].sockfd_data, pbuf, 1024, NULL);
if (recvd > 0) {
for (int i = 0; i < sz; i++) {
if (i != gp->curr_pilot && gp->users[i].unioned == TRUE)
send(gp->users[i].sockfd_data, pbuf, recvd, NULL);
}
}
delete[] pbuf;
}
客户端(发送时设置了主机,我的代码确实设置了它):
(数据是由客户端写入的双精度结构,cdata 是写入客户端的副本)。
while (kill_dataproc == FALSE) {
if (master == TRUE) {
char* buff = new char[1024];
int packet_signer = 1192;
memcpy_s(buff, intsz, &packet_signer, intsz);
memcpy_s((void*)(buff + intsz), sz, data, sz);
send(server_sock, buff, buffsize, NULL);
delete[] buff;
}
else {
char* buffer = new char[1024];
int recvd = recv(server_sock, buffer, 1024, MSG_PEEK);
if (recvd > 0) {
int newpacketsigner = 0;
memcpy_s(&newpacketsigner, intsz, buffer, intsz);
if (newpacketsigner == 1192) {
if (recvd >= buffsize) {
char* nbuf = new char[buffsize];
int recvd2 = recv(server_sock, nbuf, buffsize, NULL);
int err = WSAGetLastError();
memcpy_s(&newpacketsigner, intsz, nbuf, intsz);
memcpy_s(cdata, sz, (void*)(nbuf + intsz), sz);
//do things w/ the struct
delete[] nbuf;
}
}
else
recv(server_sock, buffer, 1024, NULL);
}
delete[] buffer;
}
Sleep(10);
}
同样,对 setsockopt 和客户端套接字的调用相同,所有套接字(服务器和客户端)都是非阻塞的。
【问题讨论】:
-
我建议简化您的程序,直到问题消失(那么原因可能是您删除的问题)或者它足够简单和完整以供其他人理解。您可以尝试从删除对我来说可疑的 Sleep(10) 开始。
-
Sleep(10) 是为了防止此循环占用客户端系统上 100% 的 CPU 使用率。
-
如果您需要休眠以不吸 CPU,那么您的非阻塞 I/O 完全错误(您说套接字是非阻塞的)。
-
@SteffenUllrich 他到底在哪里说的?
-
这里是正确的 - 他们是。那我该怎么办呢?
标签: c++ sockets tcp buffer delay