【发布时间】:2016-02-23 13:41:29
【问题描述】:
我需要实现一个服务器代码来接收表达式的长度并将从客户端接收它,它应该等待最多 500 毫秒,如下所述:
"当服务器收到长度消息时,它将等待最多 500 毫秒以发送该字节数。"
该程序由一个简单的 UDP 服务器-客户端程序组成,客户端发送一个表达式,服务器对其进行处理。我正在使用sendto() 和recvfrom() 分别在客户端/服务器之间发送数据。
此代码应该在 unix 机器上运行。我看到一个类似的question 有同样的问题,它已经解决了,但不适合我。我已将代码更改为与 recvfrom() 系统调用更相似,但它仍然不起作用。有人能猜出为什么它不起作用吗?
ssize_t timeout_recvfrom(int sock, void *restrict buf, size_t length, int flags,
struct sockaddr_in *restrict connection, socklen_t *restrict len, float timeout){
fd_set socks;
struct timeval t;
FD_ZERO(&socks);
FD_SET(sock, &socks);
t.tv_sec = timeout;
int aux = select(sock + 1, &socks, NULL, NULL, &t);
long recvlen = recvfrom(sock, buf, length, 0, (struct sockaddr *) connection, len);
if (aux && recvlen != -1) {
return recvlen;
}
else {
printf("select value: %d and recvlen: %lu\n",aux,recvlen);
perror("cannot select()");
return 0;
}
}
服务器这样调用这个函数:
//recvlen = recvfrom(fd, buf, sizeof(buf) - 1, 0, NULL, 0);
recvlen = timeout_recvfrom(fd, buf, sizeof(buf) - 1, 0, NULL, 0, 0.5);
注释版本有效,另一个无效,它输出:
select value: 0 and recvlen: 5
cannot select(): Undefined error: 0
Received 0 bytes
Received message: ""
Invalid term: `(null)'
recvlen() 应该有一个 5 的值,我猜aux 不应该是 0。
【问题讨论】:
-
您调用 select 返回 0,表示超时已过。您没有初始化超时的微秒部分,并且由于您使用 0.5 作为超时调用函数,因此秒部分的秒部分被初始化为 0(微秒部分可能是垃圾)。
-
不要在产生错误的函数调用和
perror()之间使用printf()。 -
不要在产生错误的函数调用和 perror() 之间呼吸
-
您可能会错过产生它的函数中的错误。 perror 打印 errno 的值,它可以在瞬间改变。
-
@ryyker 这不是小问题,这才是重点! timeval 未正确初始化,浮点值错误地用于设置整数类型。 OP:如果选择失败,您也不应该尝试调用接收...您的代码逻辑已损坏。
标签: c sockets unix time timeout