4

このアプリケーションが で終了する理由がわかりませんsend。サーバーのコードは次のとおりです。

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <stdlib.h>
#include <errno.h>

#define UNIX_PATH_MAX    108
#define SPATH "./sock"

int main() {
    int sfd, rv = 100, newfd;
    char b[100];
    char ok[3] = "ok\0";
    struct sockaddr_un sa;

    sfd = socket(AF_UNIX, SOCK_STREAM, 0);

    strncpy(sa.sun_path, SPATH, UNIX_PATH_MAX);
    sa.sun_family = AF_UNIX;

    if (bind(sfd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    if (listen(sfd, SOMAXCONN) == -1) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    if ((newfd = accept(sfd, NULL, NULL)) == -1) {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    while (rv != -1 && rv != 0) {
        rv = recv(newfd, b, 100, 0);

        printf("%s\n", b);

        sleep(3);

        printf("Send reply\n");
        send(newfd, ok, 3, 0);
        printf("Sent reply\n");
    }

    printf("END\n");
}

残念ながら、クライアントがCtrl+Cメッセージを送信するとすぐに強制的に閉じられた場合、サーバーは次のように出力します (最後の行として):

before send

そして、何もせずに死んでいきます。senderrno など ( if ステートメントでの呼び出しを含む) をチェックしようとしましたが、sendそれ自体がサーバーを停止させる原因のようです。で試してみましたwriteが同じです。

リターン コードを bash で確認したところ、リターン コード 141 で終了し、意味がわかりませんでした。

試してみたい場合は、クライアント コードを次に示します。

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>

#define UNIX_PATH_MAX    108
#define SPATH "./sock"

int main() {
    int sfd, rv;
    char b[100];
    char ok[3];
    struct sockaddr_un sa;

    sfd = socket(AF_UNIX, SOCK_STREAM, 0);

    strncpy(sa.sun_path, SPATH, UNIX_PATH_MAX);
    sa.sun_family = AF_UNIX;

    connect(sfd, (struct sockaddr*)&sa, sizeof(sa));

    while (scanf("%s", b)) {
        send(sfd, b, 100, 0);

        recv(sfd, ok, 3, 0);

        printf("%s\n", ok);
    }

    printf("END\n");
}

両方をコンパイルして実行し、メッセージが送信された直後に Ctrl+C でクライアントを強制終了します。

4

2 に答える 2

14

send()すでに閉じられている接続を呼び出すと、オペレーティング システムがSIGPIPEプロセスに発行する場合があります。通常、デフォルトのハンドラーSIGPIPEはプロセスを強制終了します。

これが発生しないようにするには、シグナルを無視するか (signal(SIGPIPE, SIG_IGN)または などを使用sigignore(SIGPIPE))、MSG_NOSIGNALオプションを に渡すことができsend()ます。

int send_result = send(newfd, ok, 3, MSG_NOSIGNAL);
if (send_result >= 0) {
    /* okay, but check if all your data got sent! */
    if (send_result < 3) /* ...do something */;
} else {
    switch (errno) {
    /* ... */
    case EPIPE:
        /* sending on a closed connection... */
    }
}

ここで、 を発行する代わりにSIGPIPEsend()呼び出しは失敗し、errnoに設定されEPIPEます。

于 2013-06-27T00:33:02.557 に答える
0

サーバー側で、クライアントが接続を閉じたかどうかを確認します。

rv = recv(newfd, b, 100, 0);
if(rv<=0) {
        if(!rv) {
             fprintf(stderr, "conn. closed.");
        } else {
              perror("recv");
        }
        exit(EXIT_FAILURE);
}
于 2013-06-27T00:39:32.337 に答える