我正在 Debian linux 上使用 isc-dhcp-server 运行本地 DHCP 服务器,地址 10.0.0.1。我在 10.0.0.99 上有一个中继,每 4 秒左右通过 HTTP 请求向该中继发送一个脉冲。
伪代码的工作原理如下:
while (1) {
get curr_time
if ((webrelay->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <= 0) {
log_perror(MYNAME "socket invalid for webrelay %i", webrelay->webrelay_id);
usleep(4000 * 1000);
continue;
}
if ((flags = fcntl(webrelay->socket, F_GETFL, 0)) == -1)
log_error("fcntl fail for webrelay");
else
fcntl(webrelay->socket, F_SETFL, flags | O_NONBLOCK);
if (setsockopt(webrelay->socket, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) < 0)
perror("setsockopt fail for webrelay");
relay_socket.sin_family = AF_INET;
relay_socket.sin_port = htons((unsigned short)webrelay->net_port);
relay_socket.sin_addr.s_addr = webrelay->net_address.s_addr;
if (connect(webrelay->socket, (const struct sockaddr*)&relay_socket, sizeof(relay_socket)) < 0) {
switch (errno) {
case EINPROGRESS:
while (1) {
if time_now - curr_time > 4 seconds,
print "connect slow", close socket and next iteration of for loop
else
fds[0].fd = webrelay->socket;
fds[0].events = POLLIN | POLLOUT;
fds[0].revents = 0;
if (poll(fds, sizeof(fds) / sizeof(fds[0]), 1) < 0) {
log "connect fail", close socket and next iteration of for loop
}
if (fds[0].revents & (POLLIN | POLLOUT))
break;
case OTHER_ERROR_HANDLING:
these cases never get called
}
}
send(webrelay->socket, state_xml, sizeof(state_xml), MSG_DONTWAIT) //and perform error checks
shutdown(webrelay->socket, SHUT_RDWR);
close(webrelay->socket);
webrelay->socket = 0;
//wait short amount and to next iteration
}
不幸的是,在让计算机打开多天后,我不断从 connect() 中收到这些 EINPROGRESS 错误,这意味着 connect() 需要花费几秒钟的时间。如果我将连接设置为正常阻塞模式,则会在 connect() 调用上收到超时错误。结果,继电器关闭,因为连接需要很长时间,并且最后一个脉冲在发送新脉冲之前就过期了。
所有其他网络功能调用都可以无缝工作,并且据我所知,tshark 在该以太网接口上没有显示任何异常数据包(请参阅https://pastebin.com/kTfwc5sr,其中 10.0.0.100 只是另一个不相关的设备)。
我可以做些什么来提高 connect() 调用的性能吗?