【发布时间】:2013-02-27 12:58:07
【问题描述】:
客户报告了一个我无法理解的错误。基于 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);
}
读取调用是否有可能永远阻塞,即使在连接关闭后也是如此?
我的包装器中是否有某种我没有注意到的棘手错误可能导致这种情况?我应该为连接时的套接字设置一些标志吗?
【问题讨论】:
-
是否有理由不使用它非阻塞并在 fd 上放置
select代替? -
不,没有。这样做可能是一个解决方案。我可以想到其他一些方法,这将是一个很好的解决方法。但我想知道问题的根源。
标签: c sockets tcp client-server buffer