当断开连接时我正试图'抓住'.但实际上我没有弄到什么问题.recv()返回0,errno设置为0,ioctl返回0.我在网上搜索了6个小时,但没有成功.谁能告诉我什么是错的?
问候.
bool Network::setBlocking(bool blocking)
{
// sets blocking or non-blocking mode.
int flags = blocking ? 1 : 0;
return ioctl(this->sockfd, FIONBIO, &flags) ? false : true;
}
NetworkStatus Network::status()
{
// returns socket status.
struct timeval tv;
fd_set fd;
int result = 0;
tv.tv_sec = 3;
tv.tv_usec = 0;
FD_ZERO(&fd);
FD_SET(this->sockfd, &fd);
result = select(this->sockfd + 1, &fd, 0, 0, &tv);
if(result == -1)
{
return NETWORK_ERROR;
}
else if(result)
{
return NETWORK_READYREAD;
}
else
{
return NETWORK_TIMEOUT;
}
}
int Network::bytesAvailable()
{
// returns number of bytes available.
int bytes = 0;
if(ioctl(this->sockfd, FIONREAD, &bytes) < 0 || errno)
{
return -1;
}
return bytes;
}
int Network::read(char *buffer, int size)
{
// reads data from socket.
return recv(this->sockfd, buffer, size, 0);
}
...
int main(int argc, char* argv[])
{
Network net;
...
while(true)
{
switch(net.status())
{
...
case NETWORK_READYREAD:
{
int bytesAvailable = net.bytesAvailable();
char temp[bytesAvailable];
int len = net.read(temp, bytesAvailable);
printf("len: %d\nerrno: %d\nbytesAvailable: %d\n", len, errno, bytesAvailable); // len: 0, errno: 0, bytesAvailable: 0
break;
}
}
} // status
return 0;
}
Run Code Online (Sandbox Code Playgroud)
小智 5
当另一侧关闭套接字或执行shutdown(Send)时,选择将在您这一侧返回该套接字可读,因此select命令将返回,1指示有待读取的数据(实际上没有数据,它是只是一个指示套接字已关闭的信号),但是ioctl返回的0字节数和返回的字节数recv()也0正是如此,这正是TCP的工作方式。因此,在您的程序中,您应该注意bytesAvaliablereturn 0和/或read()return 0。在这些情况下,插座已关闭,您也应该合拢并等待(接受)或建立(连接)新连接。
编辑:添加命令:
好吧,不完全是。如果为recv() = 0,则套接字处于关闭状态,或者关闭套接字以进行发送时关闭= -1。如果套接字是非阻塞的(已O_NONBLOCK设置),则应检查错误(errno在Unix上,WSAGetLastError()在Windows上),EWOULDBLOCK或者或EAGAIN指示没有可用数据,并且套接字仍然有效。另外,在极少数情况下,recv()可能会返回-1并返回错误EINTR,这意味着在recv()操作过程中已收到中断(信号),在这种情况下,您应该忽略该错误(除非您正在等待此类信号)并重新发出recv()。
ret=recv(socket, buff, length, 0);
if (ret > 0)
{
// data has been received
}
else if (ret == 0)
{
// socket has been closed or shutdown for send
}
else {
// there is an error, let's see what it is
int error = errno; // or WSAGetLastError()
switch (error)
{
case EAGAIN:
case EWOULDBLOCK:
// Socket is O_NONBLOCK and there is no data available
break;
case EINTR:
// an interrupt (signal) has been catched
// should be ingore in most cases
break;
default:
// socket has an error, no valid anymore
return;
}
}
Run Code Online (Sandbox Code Playgroud)
话虽如此,您必须清楚的一件事是,如果recv()return 0 或-1套接字不再有效并且应该关闭,但是又取决于许多因素,用于在套接字之间进行对话的协议(如果不是) -阻塞等。例如,另一端可以发出shutdown(); 在这种情况下,您recv()将返回,0但仍然可以send()通过该套接字完成操作而不会出错。