4

マルチスレッドのクライアントサーバーアプリケーションがあります。最初のスレッドは、ファイル記述子の配列にクライアントを追加する「リスナー」です。

while (1) {
    if ((connfd = accept(listenfd_service, (struct sockaddr *) &cliaddr, &clilen)) > 0) {
        printf("service connected...\n");
        int i;
        for (i = 0; i < MAX_SERVICES; i++) {
            if (service_sockets[i] == -1) {
                service_sockets[i] = connfd;
                break;
            }
        }
    }
}

問題は、Ctrl + Cでクライアントを終了し、次の行を実行すると

for (j = 0; j < MAX_SERVICES; j++) {
    if (service_sockets[j] != -1) {
        int test = write(service_sockets[j], c, 72);
        if (test == -1) {
            service_sockets[j] = -1;
        }
    }
}

'test'変数で72を取得します。これらの行を2回実行しようとすると、SIGPIPEシグナルが表示されます。

4

1 に答える 1

4

これは正常で予想される動作です。通常、ネットワーク接続を介してデータが送信されていない場合、データが送信されていないため、サーバーはクライアントが終了したときにすぐに検出しません。代わりに、次にサーバーがデータを送信すると、パケットが送信され(72バイトの書き込みが成功します)、クライアントマシン(OSがまだ実行されている場合)は「接続リセット」メッセージで応答します。これにより、サーバーOSが接続の終了を閉じ、サーバーが次にソケットに書き込むときにSIGPIPE/EPIPEが発生します。

これを処理する通常の方法は、SIGPIPEシグナルを無視し、EPIPEエラーを返す書き込みを処理することです。複数の接続を処理し、他の接続がまだ有用である間に1つがなくなる可能性があるほとんどすべてのプロセスは、SIGPIPEを無視する必要があります。

于 2012-06-08T19:31:36.600 に答える