2

ブロッキングconnect()呼び出しを使用する既存のマルチスレッドアプリケーションがあります。

ただし、サーバーがxミリ秒以内にクエリに応答しない場合、アプリケーションは試行を停止してエラーを発生させるアプリケーションの接続タイムアウトを導入したいと思います。

ただし、ポーリングを使用してそれを行う方法を理解することはできません。

selectを使用した@cafのノンブロッキング接続は非常に役立ちました。しかし、私はその選択をポーリングに比べて遅いので読んだので、ポーリングを使用したいと思います。それが本当かどうか教えていただけますか?

ここの投稿から彼のコードを貼り付けています

int main(int argc, char **argv) {
u_short port;                /* user specified port number */
char *addr;                  /* will be a pointer to the address */
struct sockaddr_in address;  /* the libc network address data structure */
short int sock = -1;         /* file descriptor for the network socket */
fd_set fdset;
struct timeval tv;

if (argc != 3) {
    fprintf(stderr, "Usage %s <port_num> <address>\n", argv[0]);
    return EXIT_FAILURE;
}

port = atoi(argv[1]);
addr = argv[2];

address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(addr); /* assign the address */
address.sin_port = htons(port);            /* translate int2port num */

sock = socket(AF_INET, SOCK_STREAM, 0);
fcntl(sock, F_SETFL, O_NONBLOCK);

connect(sock, (struct sockaddr *)&address, sizeof(address));

FD_ZERO(&fdset);
FD_SET(sock, &fdset);
tv.tv_sec = 10;             /* 10 second timeout */
tv.tv_usec = 0;

if (select(sock + 1, NULL, &fdset, NULL, &tv) == 1)
{
    int so_error;
    socklen_t len = sizeof so_error;

    getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len);

    if (so_error == 0) {
        printf("%s:%d is open\n", addr, port);
    }
}

close(sock);
return 0;

}

ポーリングを使用して同様の機能を作成するのを手伝っていただけませんか。

私はRHELを使用しており、gcc4.5.xバージョンを使用しています。

更新:現在のコードの場合、アプリがサーバーへの接続を作成したら、ソケットをブロッキングモードに変更するにはどうすればよいですか。このO_NONBLOCKの設定を解除する方法を見つけることができません。 更新2:fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) & ~O_NONBLOCK); ある投稿では、上記のコマンドでこれを実行できると指摘されています。しかし、ログインを取得できませんでした。

4

2 に答える 2

5

ポーリングされているファイル記述子が少ない場合、他のシステム依存のポーリングAPIと比較したselect()およびpoll()のパフォーマンスは同等です。どちらもスケーリングが不十分ですが、プログラムが数fdsしかリッスンしていない場合は、問題なく動作します。

他のシステム固有のポーリングAPIの利点は、関連付けられた状態をカーネルにプッシュするため、各ポーリングシステムコールがユーザースペースからカーネルスペースへの状態のコピーを必要としないことです。わずかなイベントで、このコピーとスキャンのオーバーヘッドは重要ではなく、この利点は存在しません。

数百以上のfdsを処理するようにスケーリングする必要がない限り、select()を使用してください。

実際に多くのfdsを処理し、LinuxとSolarisの両方をサポートする必要がある場合は、libeventlibevなどのライブラリを使用して、カーネル固有の効率的な待機APIを抽象化することを検討してください。

于 2011-09-22T15:18:38.093 に答える
-1

selectポーリングより遅くなることはありません。しかし、たとえそうであったとしても、アプリケーションで最小限の違いが問題になる可能性はほとんどありません。

ノンブロッキングタイムアウト接続を行うために、そのような機能を提供する既存のアプリケーションからコピーすることができます。(これを行う方法については、たとえばここを参照してください)。

于 2011-09-22T14:38:25.090 に答える