0

サーバー データを受信するソケットを作成し、ノンブロッキング モードを採用していますが、select が常にゼロを返す理由がわかりません。これにより、プレーヤーが再生または一時停止します。さらに情報が必要な場合はお知らせください。

int ret = 0;
int timeout = 0;
while(http->work_flag)
{
    fd_set  readSet;
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = 80*1000;
    FD_ZERO( &readSet );
    FD_SET( http->fd, &readSet );
    ret = select(http->fd + 1,&readSet,0,0,&tv);
    printf("%d\r\n",ret);
    if ( ret > 0 ) {
        ret = recv(http->fd,buf,size,0);
        if( ret <= 0 ){
            ret = -1;       
        }
        else {
            http->total_bytes += ret;
            http->continue_pkt++;   
        }
        return ret;
    }   
    else if( ret < 0 ) {
        http->continue_pkt = 0;
        return  -1;
    }   
    else if( ret == 0 ) {
        http->continue_pkt = 0;
        //time out
        timeout++;
        if( timeout > 12*30 ) //30seconds
            return -1;//timeout
    }
}
return -1;
4

1 に答える 1

0

ループを完全に取り除きselect()、タイムアウトを管理させた場合、同じ問題がありますか?

fd_set  readSet;
struct timeval tv;

tv.tv_sec = 30;
tv.tv_usec = 0;

FD_ZERO( &readSet );
FD_SET( http->fd, &readSet );

int ret = select(http->fd + 1, &readSet, 0, 0, &tv);
printf("%d\r\n", ret);

if( ret <= 0 )
{
    // error or timeout
    http->continue_pkt = 0;
    return -1;
}

ret = recv(http->fd, buf, size, 0);
if( ret <= 0 )
{
    // error or disconnect
    return -1;
}

http->total_bytes += ret;
http->continue_pkt++;   
return ret;

select()短いタイムアウトでループを呼び出す唯一の理由は、読み取りロジックをできるだけ早く中止させようとしている場合です。そのためには、別のパイプ ビアを作成し、それをソケットpipe()と同じ場所に配置してfd_setから、パイプに何かを書き込んで、select()必要に応じて「ウェイクアップ」させることができます。がselect()返さ> 0れると、コードはパイプにシグナルが送信されたかどうかを確認し、シグナルが送信されたrecv()場合は呼び出さずに終了できます。

于 2013-10-16T04:04:08.983 に答える