Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 断开连接时,非阻塞recv返回0_C++_C_Sockets - Fatal编程技术网

C++ 断开连接时,非阻塞recv返回0

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

当断开连接时,我试图“捕捉”。 但我真的不明白怎么回事。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;
}
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()
return
0
-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;
   }
}