1

このコードに問題があります:

FD_ZERO(&cset);
FD_SET(s, &cset);

tval.tv_sec = TIMEOUT; 
tval.tv_usec = 0; 

n = select(FD_SETSIZE, &cset, NULL, NULL, &tval);

if (n==-1) {
    printf(" select() failed \n");
    exit(-1);
}
if (n>0) {
    check_control = connect(s,(struct sockaddr*)
    &indirizzo_remoto,sizeof(indirizzo_remoto));

    if (check_control == -1) {
        printf("Errore connect()\n");
    }

}else{
    printf("Timeout. I'll shutdown the client");
    exit(-1);
}

接続のタイムアウトを挿入したいのですが、うまくいきません:

サーバーの正しい IP アドレスとポート番号を使用していますが、接続がタイムアウトになります。

助けてくれてありがとう。

4

1 に答える 1

4

同じソケットを呼び出す前select()に、特定のソケットが読み取り可能な状態にあるかどうかを確認するために使用しています。connect()それは決してうまくいきません。接続されていない TCP ソケットは読み取り可能な状態になることはなく、最初に呼び出されるselect()まで使用できません。connect()

呼び出しのタイムアウトを実装する唯一の方法connect()は、最初にソケットを非ブロッキング モードにし (ソケットはデフォルトでブロックされます)、次に呼び出し(ソケットが接続しようとするとエラーconnect()を返します) を使用して待機することです。ソケットが書き込み可能状態 (接続が成功したことを示す) になるか、エラー状態 (接続が失敗したことを示す) になります。EINPROGRESSselect()

これを試して:

fcntl(s, F_SETFL, O_NONBLOCK);

または:

flags = 1;
ioctl(s, FIOBIO, &flags);

プラットフォームによって異なります。

それで:

check_control = connect(s, (struct sockaddr*) &indirizzo_remoto, sizeof(indirizzo_remoto));
if (check_control == -1)
{
    if (errno != EINPROGRESS)
    {
        printf("Errore connect()\n");
        exit(-1);
    }

    FD_ZERO(&wset);
    FD_SET(s, &wset);

    FD_ZERO(&eset);
    FD_SET(s, &eset);

    tval.tv_sec = TIMEOUT; 
    tval.tv_usec = 0; 

    n = select(s+1, NULL, &wset, &eset, &tval);
    if (n == -1)
    {
        printf(" select() failed \n");
        exit(-1);
    }

    if (n == 0)
    {
        printf("Timeout. I'll shutdown the client");
        exit(-1);
    }

    if (FD_ISSET(s, &eset))
    {
        printf("Cannot connect. I'll shutdown the client");
        exit(-1);
    }

    int err = -1;
    getsockopt(s, SOL_SOCKET, SO_ERROR, &err, sizeof(err));
    if (err != 0)
    {
        printf("Cannot connect. I'll shutdown the client");
        exit(-1);
    }
}

// connected...
于 2013-06-12T21:28:03.043 に答える