接受 returns 0 用于第二个、第三个等客户端
accept returns 0 for 2nd, 3rd, etc client
我正在编写一个简单的套接字 server/client 应用程序。
我运行陷入有趣的问题。在我的服务器代码中,我像这样在非阻塞套接字上调用 accept
while ((res = accept(m_sd, NULL, 0)) >= 0) { // There are new clients
... // Saving res as fd etc
}
一切正常 - 当有客户端时,接受 returns 一个有效的文件描述符。然而,当第一个客户端断开连接而第二个客户端连接时,接受 returns 0 - 这是一个有效的 FD,但是对此描述符的所有操作都会失败。对于下一个客户也会发生这种情况 - 接受返回 0。在随机数量的客户之后,接受者 returns 一个 "valid"(非零)描述符,然后重复。
注意:当没有客户端时,按预期接受 returns -1 errno EAGAIN - 这完全没问题。当接受 returns 零时,不设置 errno。
什么会导致这种奇怪的行为?
以下是我创建服务器套接字的方法:
struct sockaddr_in serv_addr;
m_sd = socket(AF_INET, SOCK_STREAM, 0);
if (m_sd < 0){}
//Handle error
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port);
int optval = 1;
setsockopt(m_sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
if (bind(m_sd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
// Handle error
}
fcntl(m_sd, F_SETFL, O_NDELAY); // Make socket non-blocking
listen(m_sd, 50);
下面是我创建客户端的方式:
int rc;
struct sockaddr_in serveraddr;
struct hostent *hostp;
m_sd = socket(AF_INET, SOCK_STREAM, 0);
if (m_sd < 0)
// Handle error
memset(&serveraddr, 0, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(port);
hostp = gethostbyname(hostname.c_str());
if (hostp == NULL)
// Handle error
memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));
// connect to serveraddr
rc = connect(m_sd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
if (rc < 0)
//Handle error
//set to nonblocking
fcntl(m_sd, F_SETFL, fcntl(m_sd, F_GETFL, 0) | O_NONBLOCK);
这是我等待来自任何客户端的新数据的代码:
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(timeout).count();
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(m_sd, &rfds);
int end = m_sd;
for (const auto& s : m_clients) {
end = std::max(end, s.second.m_sd);
FD_SET(s.second.m_sd, &rfds);
}
int retval = select(end + 1, &rfds, NULL, NULL, &tv);
if (retval == -1) {
// Error handling
}
return retval > 0; // There is pending data from client
问题解决了!我不小心在我的代码中关闭了 fd 0,这导致了这种奇怪的行为。现在一切正常。感谢您的帮助 - 您向我展示了正确的方法
我正在编写一个简单的套接字 server/client 应用程序。 我运行陷入有趣的问题。在我的服务器代码中,我像这样在非阻塞套接字上调用 accept
while ((res = accept(m_sd, NULL, 0)) >= 0) { // There are new clients
... // Saving res as fd etc
}
一切正常 - 当有客户端时,接受 returns 一个有效的文件描述符。然而,当第一个客户端断开连接而第二个客户端连接时,接受 returns 0 - 这是一个有效的 FD,但是对此描述符的所有操作都会失败。对于下一个客户也会发生这种情况 - 接受返回 0。在随机数量的客户之后,接受者 returns 一个 "valid"(非零)描述符,然后重复。
注意:当没有客户端时,按预期接受 returns -1 errno EAGAIN - 这完全没问题。当接受 returns 零时,不设置 errno。
什么会导致这种奇怪的行为?
以下是我创建服务器套接字的方法:
struct sockaddr_in serv_addr;
m_sd = socket(AF_INET, SOCK_STREAM, 0);
if (m_sd < 0){}
//Handle error
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port);
int optval = 1;
setsockopt(m_sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
if (bind(m_sd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
// Handle error
}
fcntl(m_sd, F_SETFL, O_NDELAY); // Make socket non-blocking
listen(m_sd, 50);
下面是我创建客户端的方式:
int rc;
struct sockaddr_in serveraddr;
struct hostent *hostp;
m_sd = socket(AF_INET, SOCK_STREAM, 0);
if (m_sd < 0)
// Handle error
memset(&serveraddr, 0, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(port);
hostp = gethostbyname(hostname.c_str());
if (hostp == NULL)
// Handle error
memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));
// connect to serveraddr
rc = connect(m_sd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
if (rc < 0)
//Handle error
//set to nonblocking
fcntl(m_sd, F_SETFL, fcntl(m_sd, F_GETFL, 0) | O_NONBLOCK);
这是我等待来自任何客户端的新数据的代码:
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(timeout).count();
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(m_sd, &rfds);
int end = m_sd;
for (const auto& s : m_clients) {
end = std::max(end, s.second.m_sd);
FD_SET(s.second.m_sd, &rfds);
}
int retval = select(end + 1, &rfds, NULL, NULL, &tv);
if (retval == -1) {
// Error handling
}
return retval > 0; // There is pending data from client
问题解决了!我不小心在我的代码中关闭了 fd 0,这导致了这种奇怪的行为。现在一切正常。感谢您的帮助 - 您向我展示了正确的方法