TCP套接字已设置为非阻塞。
以下是代码:
char * recv_response(int sockfd)
{
char * resp_msg = (char *)malloc(MAX_RESP_LEN);
int n, len;
len = 0;
while (1) {
n = read(sockfd, resp_msg + len, 1024);
printf("#recv_response. n = %d, len = %d#\n", n, len);
if (n < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
printf("#recv_response. errno = EAGAIN#\n");
sleep(5);
continue;
}
else if (errno == EINTR) {
printf("recv interruputed\n");
close(sockfd);
return NULL;
}
}
else if (n == 0)
break;
else
len += n;
}
close(sockfd);
resp_msg = realloc(resp_msg, len + 1);
return resp_msg;
}
以下是将GET请求发送到网页时的工作原理:
#recv_response. n = -1, len = 0#
#recv_response. errno = EAGAIN#
#recv_response. n = 1024, len = 0#
#recv_response. n = 1024, len = 1024#
#recv_response. n = 1024, len = 2048#
#recv_response. n = 1024, len = 3072#
#recv_response. n = 1024, len = 4096#
#recv_response. n = 909, len = 5120#
#recv_response. n = -1, len = 6029#
#recv_response. errno = EAGAIN#
#recv_response. n = -1, len = 6029#
#recv_response. errno = EAGAIN#
#recv_response. n = -1, len = 6029#
#recv_response. errno = EAGAIN#
#recv_response. n = -1, len = 6029#
#recv_response. errno = EAGAIN#
^C
read()
应返回n = 0,以便在读取网页中的所有内容后停止while循环。但这不是。
更新: 当我在办公室测试此代码时,会出现上述故障情况。当我回到家时它起作用:
#recv_response. n = -1, len = 0#
#recv_response. errno = EAGAIN#
#recv_response. n = 1024, len = 0#
#recv_response. n = 1024, len = 1024#
#recv_response. n = 1024, len = 2048#
#recv_response. n = 1024, len = 3072#
#recv_response. n = 1024, len = 4096#
#recv_response. n = 227, len = 5120#
#recv_response. n = 0, len = 5347#
HTTP/1.1 200 OK
我知道公司网络中的防火墙可能会禁用某些网络服务,例如ping
,但为什么read()
可以读取内容但无法停止?
答案 0 :(得分:1)
read()应返回n = 0,以便在读取网页中的所有内容后停止while循环。
不,不应该。当对等体关闭连接时,它应该返回零。
您是HTTP keep-alive的受害者。如果您不想这样,请发送标题Connection: close
。否则你需要读取所有标题,然后从Content-length
标题中获取正文大小,并准确读取那么多字节。
请注意,以这种方式使用非阻塞套接字完全没有意义。你的睡眠时间太短或太长。阻塞模式recv()
或read()
阻塞了恰当的时间长度,它是一行代码。如果您想要套接字超时,请设置SO_RCVTIMEO.