我的TCP服务器传输数据包传输延迟似乎有问题。现在,此服务器必须是TCP,因为UDP被防火墙阻止(这是客户端 - 服务器 - 客户端类型的通信)。我也知道发送一个浮点整数的结构非常不便携,但是,在可预见的将来,这个系统将Windows客户端运行到Windows服务器到Windows客户端。
问题在于:客户端开始从另一个客户端正确接收数据,但是,有一个延迟会呈指数级下降(其中,大约3分钟后,数据包将落后近30秒 - 但是正确,当他们到达时)。我研究了它并在微软页面上找到了一个答案,解释它是由于完整的发送缓冲区,但是,它们的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并调用客户端的套接字,并且所有套接字,服务器和客户端都是非阻塞的。
答案 0 :(得分:0)
您假设您的读取正在填充缓冲区。他们只需要传输至少一个字节。你需要循环。
因此,您有未读数据备份并拖延发件人。
注意那些接收缓冲区大于64k,因此除非在连接套接字之前设置它们,否则可能无效。对于服务器,您需要在侦听套接字上设置接收缓冲区大小。接受的套接字将继承它。如果你不这样做,窗口缩放将不会生效,因此窗口&gt;无法公布64k(除非平台默认启用窗口缩放)。