一位客户报告了一个我无法理解的错误。基于 TCP 的客户端连接到它从中接收数据的服务器,很少发送任何东西。通常一切正常,但在极少数情况下会发生这样的情况:
- 服务器发送一些数据
- 客户端接收数据
- 客户端正在处理数据
- ...同时服务器发送更多数据
- 客户完成处理
- 客户端尝试从套接字读取数据
- 客户端在处理后永远卡在第一个 read() 语句上
- 服务器关闭连接
- 客户端仍然挂起
这是建立 tcp 连接的方式(去除所有日志、返回检查等)
ret = inet_pton(AF_INET, conn->address, &addr.sin_addr);
addr.sin_port = htons(conn->port); /* Server port */
addr.sin_family = AF_INET;
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(sock, (struct sockaddr *) &addr, sizeof(addr));
这是读取包装器:
int32_t _readn ( int fd, uint8_t *vptr, int32_t n )
{
int32_t nleft;
int32_t nread;
uint8_t* ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ((nread = read (fd, ptr, nleft)) < 0) {
if (errno == EINTR) {
nread = 0;
} else {
return E_NETWORK_ERROR;
}
} else if ( nread == 0 ) {
break;
}
nleft -= nread;
ptr += nread;
}
return (n-nleft);
}
读取调用是否可能永远阻塞,即使在连接关闭后也是如此?
我的包装器中是否存在某种我没有注意到的棘手错误可能会导致这种情况?我应该在连接时为套接字设置一些标志吗?
最佳答案
问题的根源是如果没有数据读取就会阻塞。例如。如果写入的字节少于预期的 n 个字节。这称为阻塞读取。
如 Jite 所说,要发现是否有数据,请使用 select
。
最后,您的防火墙可能会断开实时连接。一些防火墙配置为切断打开时间超过给定时间的连接,例如30分钟。然而,这可能不是您所拥有的。
关于c - tcp 套接字读取调用如何永远不会返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15112717/