select
检查流上是否有数据可用。我总是一次性读写40个字节。虽然大多数读取只需要几毫秒或更少的时间,但有些读取需要超过半秒钟的时间。在我知道套接字上有数据可用之后。我还使用了
TCP_NODELAY
这是什么原因?编辑2
我分析了每个发送和接收的数据包的时间戳,并发现只有在客户端尝试在服务器写入下一个对象之前读取对象时才会出现此延迟。例如,服务器写入对象编号x,之后客户端尝试在服务器能够开始写入对象编号x + 1之前读取对象x。这使我怀疑服务器端正在进行某种合并。
编辑
服务器正在侦听3个不同的端口。客户端逐个连接到这些端口中的每一个。
有三个连接:一个从服务器经常向客户端发送一些数据。第二个仅从客户端发送数据到服务器。第三个很少使用,只发送单个字节的数据。我遇到了第一个连接的问题。我使用
select()
检查该连接上是否有数据可用,然后当我对40个字节进行时间戳读取时,我发现需要大约半秒钟才能完成该读取。任何关于如何对此进行分析的指针都将非常有帮助
在Linux上使用gcc。 rdrr_server_start(void) { int rr_sd; int input_sd; int 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); }
static int getTcpConnection(int sd) { socklen_t len; struct sockaddr_in clientAddress; len = sizeof(clientAddress); int connFD = accept(sd, (struct sockaddr*) &clientAddress, &len); nodelay(connFD); fflush(stdout); return connFD; }
static void startTcpServer(int *sd, const int port) { *sd= socket(AF_INET, SOCK_STREAM, 0); ASSERT(*sd>0);
//设置套接字选项,以便可以重用端口 int enable = 1; setsockopt(*sd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); }
结构体 sockaddr_in a;使用 memset 函数将其初始化为零,并设置其大小;a.sin_family 设置为 AF_INET;a.sin_port 设置为端口号 port;a.sin_addr.s_addr 设置为 INADDR_ANY(任何地址);使用 bind 函数将 socket 与地址绑定;使用 listen 函数开始监听。
函数 nodelay 的作用是禁止延迟,传入的参数为文件描述符 fd;设置 flag=1;使用 setsockopt 函数设置 SOL_TCP、TCP_NODELAY 选项,禁止 TCP 延迟;
startTcpClient 函数中先分别创建了四个套接字 connFD_rr、connFD_input、connFD_ack、connFD_fp;同样地,创建结构体 sockaddr_in a 并初始化;将 a.sin_port 分别设置为 remote_rr_port、remote_input_port、remote_ack_port、remote_fp_port;将 a.sin_addr.s_addr 设置为远程服务器 IP 地址;使用 connect 函数连接到远程服务器,并使用 ASSERT 函数判断连接是否成功;最后将四个套接字分别传递给函数 nodelay。