【发布时间】:2013-08-12 18:16:10
【问题描述】:
我正在为我的客户端和服务器使用阻塞 TCP 套接字。每当我阅读时,我首先使用select 检查流中是否有可用的数据。我总是一次读写 40 个字节。虽然大多数读取需要几毫秒或更短的时间,但有些只需要半秒以上。在我知道套接字上有可用的数据之后。
我也在用TCP_NODELAY
可能是什么原因造成的?
编辑 2
我分析了每个发送和接收的数据包的时间戳,发现只有当客户端在服务器写入下一个对象之前尝试读取对象时才会发生这种延迟。例如,服务器写入对象编号 x,然后客户端尝试读取对象 x,然后服务器才能够开始写入对象编号 x+1。这让我怀疑服务器端正在发生某种合并。
编辑
服务器正在侦听 3 个不同的端口。客户端一一连接到这些端口中的每一个。
共有三种连接:一种经常从服务器向客户端发送一些数据。第二个只将数据从客户端发送到服务器。第三个很少用于发送单字节数据。我面临第一次连接的问题。我正在使用 select() 检查该连接上的数据是否可用,然后当我为 40 字节读取添加时间戳时,我发现该读取花费了大约半秒。
任何关于如何分析它的指针都会非常有帮助
在 linux 上使用 gcc。
<pre></pre>
rdrr_server_start(无效)
{
int rr_sd;
int input_sd;
诠释 ack_sd;
int fp_sd;
startTcpServer(&rr_sd, remote_rr_port); startTcpServer(&input_sd, remote_input_port); startTcpServer(&ack_sd, remote_ack_port); startTcpServer(&fp_sd, remote_fp_port);
connFD_rr = getTcpConnection(rr_sd); connFD_input = getTcpConnection(input_sd); connFD_ack=getTcpConnection(ack_sd); connFD_fp=getTcpConnection(fp_sd); }
静态 int getTcpConnection(int sd)
{
socklen_t l en;
结构 sockaddr_in 客户端地址;
len = sizeof(clientAddress);
int connFD = accept(sd, (struct sockaddr*) &clientAddress, &len);
节点层(connFD);
fflush(标准输出);
返回 connFD;
}
静态无效 startTcpServer(int *sd, const int 端口) { *sd=套接字(AF_INET,SOCK_STREAM,0); 断言(*sd>0);
// 设置套接字选项,以便端口可以重用 诠释启用 = 1; setsockopt(*sd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
struct sockaddr_in a; memset(&a,0,sizeof(a)); a.sin_family = AF_INET; a.sin_port = 端口; a.sin_addr.s_addr = INADDR_ANY; int bindResult = bind(*sd, (struct sockaddr *) &a, sizeof(a)); 断言(绑定结果 ==0); 听(*sd,2); } 静态无效节点层(int fd){ 整数标志=1; ASSERT(setsockopt(fd, SOL_TCP, TCP_NODELAY, &flag, sizeof flag)==0); }
startTcpClient() { connFD_rr = 套接字(AF_INET,SOCK_STREAM,0); connFD_input = 套接字(AF_INET,SOCK_STREAM,0); connFD_ack = 套接字(AF_INET,SOCK_STREAM,0); connFD_fp=socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in a; memset(&a,0,sizeof(a)); a.sin_family = AF_INET; a.sin_port = remote_rr_port; a.sin_addr.s_addr = inet_addr(remote_server_ip);
int CONNECT_TO_SERVER=connect(connFD_rr, &a, sizeof(a)); ASSERT(CONNECT_TO_SERVER==0) ;
a.sin_port = 远程输入端口; CONNECT_TO_SERVER=connect(connFD_input, &a, sizeof(a)); ASSERT(CONNECT_TO_SERVER==0) ;
a.sin_port = remote_ack_port; CONNECT_TO_SERVER=connect(connFD_ack, &a, sizeof(a)); ASSERT(CONNECT_TO_SERVER==0) ;
a.sin_port = remote_fp_port; CONNECT_TO_SERVER=connect(connFD_fp, &a, sizeof(a)); ASSERT(CONNECT_TO_SERVER==0) ;
nodelay(connFD_rr); 节点层(connFD_input); 节点层(connFD_ack); 节点层(connFD_fp); }
【问题讨论】:
-
我感觉这个问题与硬件有关...
-
经常从服务端向客户端发送一些数据的一种,我们说的大小是多少?
-
也许 TCP_NODELAY(禁用 Nagle)是一个不好的选择,导致要发送许多短段,从而导致每个“逻辑”数据包多次往返。加上应用程序方面的大量系统调用。
-
@wildplasser 即使我
write()一次性完成完整的“逻辑”数据包,也会发生这种情况吗?我不允许客户端和服务器之间有任何延迟,这就是我禁用 Nagle 的原因 -
@tuxuday 正好 40 字节数据,每 10 毫秒 2-5 次