1

切断が発生したときに「キャッチ」しようとしています。しかし、実際には何が悪いのかわかりません。recv() は 0 を返し、errno は 0 に設定され、ioctl は 0 を返します。Web で 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;
}
4

2 に答える 2

7

recv()ピアが切断されるとゼロ返します。問題ありません。これは予期された正しい動作です。

于 2013-07-24T04:24:53.317 に答える
5

反対側がソケットを閉じるか、シャットダウン(送信)を行うと、あなたの側でselectはソケットが読み取り可能であることを返すため、selectコマンドは1読み取るデータがあることを示します(実際にはデータはありません。ソケットが閉じていることを示すシグナルのみ)、使用可能なバイトとしてioctl返され、また返されます。これがまさにTCPの仕組みです。したがって、プログラムでは、 returnおよび/またはreturnsを処理する必要があります。このような場合、ソケットは閉じられており、自分の側も閉じて、新しい接続を待機 (受け入れ) または確立 (接続) する必要があります。0recv()0bytesAvaliable0read()0

編集:コメントを追加:

まあ、正確ではありません。の場合、ソケットにエラーがある場合recv() = 0、ソケットは閉じられているか、送信のためにシャットダウンされています。= -1ソケットが非ブロック (O_NONBLOCK設定済み) の場合は、エラー ( errnoUNIX の場合WSAGetLastError()、Windowsの場合) をチェックするEWOULDBLOCKEAGAIN、利用可能なデータがなく、ソケットがまだ有効であることを示します。また、ごくまれに、操作中に割り込み (シグナル) が受信されたことを意味するエラーrecv()が返される場合があります。この場合、エラーを無視して (そのようなシグナルを待機していない限り) 、-1EINTRrecv()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;
   }
}

明確にしなければならないことの 1 つは、recv()戻り値 0 または-1ソケットが無効になり、閉じる必要がある場合ですが、多くの要因に依存しますが、ソケット間のダイアログを維持するために使用するプロトコルは、 -blocking など。たとえば、反対側はshutdown();を発行できます。この場合、recv()戻りますが、エラーなしでそのソケットを介して0実行できます。send()

于 2013-07-24T10:25:30.333 に答える