C++ 断开连接时,非阻塞recv返回0
当断开连接时,我试图“捕捉”。 但我真的不明白怎么回事。recv()返回0,errno设置为0,ioctl返回0。我在网上搜索了6个小时,但没有成功。谁能告诉我怎么了 问候C++ 断开连接时,非阻塞recv返回0,c++,c,sockets,C++,C,Sockets,当断开连接时,我试图“捕捉”。 但我真的不明白怎么回事。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
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;
}
bool网络::设置锁定(bool阻塞)
{
//设置阻塞或非阻塞模式。
int标志=阻塞?1:0;
返回ioctl(this->sockfd、FIONBIO和flags)?false:true;
}
网络状态网络::状态()
{
//返回套接字状态。
结构时间值电视;
fd_集fd;
int结果=0;
tv.tv_sec=3;
tv.tv_usec=0;
FD_零(&FD);
FD_集合(此->sockfd和&FD);
结果=选择(此->sockfd+1和fd、0、0和tv);
如果(结果==-1)
{
返回网络错误;
}
否则,如果(结果)
{
返回网络_READYREAD;
}
其他的
{
返回网络超时;
}
}
int网络::字节可用()
{
//返回可用的字节数。
int字节=0;
if(ioctl(this->sockfd、FIONREAD和bytes)<0 | | errno)
{
返回-1;
}
返回字节;
}
int网络::读取(字符*缓冲区,int大小)
{
//从套接字读取数据。
返回recv(此->sockfd,缓冲区,大小,0);
}
...
int main(int argc,char*argv[])
{
网络;
...
while(true)
{
开关(net.status())
{
...
案例网络_READYREAD:
{
int bytesavable=net.bytesavable();
字符温度[字节可用];
int len=net.read(temp,字节可用);
printf(“len:%d\n错误:%d\n字节可用:%d\n”,len,errno,bytesavable);//len:0,errno:0,bytesavable:0
打破
}
}
}//状态
返回0;
}
recv()
对等机断开连接时返回零。你没有问题。这是预期的、正确的行为。recv()
在对等机断开连接时返回零。你没有问题。这是预期的、正确的行为。当另一方关闭套接字或执行关机(发送)时,在您的一侧,select将返回套接字可读,因此select命令将返回1
指示有数据要读取(实际上没有数据,它只是指示套接字已关闭的信号),但是ioctl
以可用字节的形式返回0
,而recv()
也返回0
,这正是TCP的工作原理。因此,在您的程序中,您应该注意bytesavalable
返回0
和/或read()
返回0
。在这些情况下,套接字已经关闭,您也应该关闭您的端口,等待(接受)或建立(连接)新连接
编辑:添加命令:
嗯,不完全是这样。当recv()=0
时,套接字关闭或关闭以进行发送,当=-1
套接字中存在错误。如果套接字是非阻塞的(已设置了O\u NONBLOCK
项),则应检查错误(errno
在unix上,WSAGetLastError()
在Windows上),并且ewoodblock
或EAGAIN
表示没有可用数据,套接字仍然有效。此外,在一些非常罕见的情况下,recv()
可能会返回-1
和错误EINTR
,这意味着在recv()
操作期间收到了中断(信号),在这种情况下,您应该忽略错误(除非等待此类信号),然后重新发出recv()
也就是说,有一点您必须清楚,如果
recv()
返回0
或-1
套接字不再有效,应该关闭,但这取决于许多因素,您用来在套接字之间保持对话的协议,如果它处于非阻塞状态,等等,另一方可以发出shutdown()
;在这种情况下,您的recv()
将返回0
,但您仍然可以通过该套接字执行send()
,而不会出现错误。当另一侧关闭套接字或执行关机(send)时,在您一侧,选择将返回套接字可读,因此,select命令将返回1
,指示有数据要读取(实际上没有数据,它只是一个指示套接字已关闭的信号),但ioctl
将0
作为可用字节返回,recv()
也返回0
,这正是TCP的工作方式。因此,在您的程序中,您应该注意bytesavalable
返回0
和/或read()
返回0
。在这些情况下,套接字已经关闭,您也应该关闭您的端口,等待(接受)或建立(连接)新连接
编辑:添加命令:
嗯,不完全是这样。当recv()=0
时,套接字关闭或关闭以进行发送,当=-1
套接字中存在错误。如果套接字是非阻塞的(已设置了O\u NONBLOCK
项),则应检查错误(errno
在unix上,WSAGetLastError()
在Windows上),并且ewoodblock
或EAGAIN
表示没有可用数据,套接字仍然有效。此外,在一些非常罕见的情况下,recv()
可能会返回-1
和错误EINTR
,这意味着在recv()
操作期间收到了中断(信号),在这种情况下,您应该忽略错误(除非等待此类信号),然后重新发出recv()
也就是说,有一点您必须清楚,如果recv()
return0
或-1
套接字不再有效,应该关闭,但这取决于许多因素,您用于在套接字之间保持对话的协议,如果它处于非阻塞状态,例如
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;
}
}