8

小さな C クライアント/サーバー アプリケーションを作成していますが、外部 IP アドレスを使用すると接続が機能しません。クライアントとサーバーの両方のコードはhereから取得されます。特に、クライアントは次のことを行います。

    char *default_server_name = "localhost";
    char *server_name = NULL;
    int nport = DEFAULT_DAMA_PORT;
    char port[15];

    // Parse the command line options
    if (parse_options(argc, argv, &server_name, &nport) < 0) {
        return -1;
    }

    if (server_name == NULL) {
        server_name = default_server_name;
    }

    snprintf(port, 15, "%d", nport);

    // Connect to the server
    int client_socket;
    struct addrinfo hints, *servinfo, *p;
    int rv;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    if ((rv = getaddrinfo(server_name, port, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        exit(1);
    }

    for (p=servinfo; p != NULL; p = p->ai_next) {
        if ((client_socket = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
#ifdef DEBUG
            perror("socket");
#endif
            continue;
        }

        if (connect(client_socket, p->ai_addr, p->ai_addrlen) == -1) {
            close(client_socket);
#ifdef DEBUG
            perror("connect");
#endif
            continue;
        }

        // Connected succesfully!
        break;
    }

    if (p == NULL) {
        // The loop wasn't able to connect to the server
        fprintf(stderr, "Couldn't connect to the server\n.");
        exit(1);
    }

サーバーの間:

    int nport;
    char port[15];
    if (parse_options(argc, argv, &nport) < 0) {
        return -1;
    }

    snprintf(port, 15, "%d", nport);

    int server_socket;
    struct addrinfo hints, *servinfo, *p;
    int rv;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    if ((rv = getaddrinfo(NULL, port, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        exit(1);
    }

    for (p=servinfo; p != NULL; p = p->ai_next) {
        if ((server_socket = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
#ifdef DEBUG
            perror("socket");
#endif
            continue;
        }

        if (bind(server_socket, p->ai_addr, p->ai_addrlen) == -1) {
            close(server_socket);
#ifdef DEBUG
            perror("bind");
#endif
            continue;
        }

        // We binded successfully!
        break;
    }

    if (p == NULL) {
        fprintf(stderr, "failed to bind socket\n");
        exit(2);
    }

    int pl_one, pl_two;
    socklen_t pl_one_len, pl_two_len;
    struct sockaddr_in pl_one_addr, pl_two_addr;

    if (listen(server_socket, 2) < 0) {
        fatal_error("Error in syscall listen.", 2);
    }

    // Get the two clients connections.
    pl_one_len = sizeof(pl_one_addr);
    pl_one = accept(server_socket,
                    (struct sockaddr *)&pl_one_addr,
                    &pl_one_len);
    if (pl_one < 0) {
        fatal_error("Error in syscall accept.", 3);
    }

    pl_two_len = sizeof(pl_two_addr);
    pl_two = accept(server_socket,
                    (struct sockaddr *)&pl_two_addr,
                    &pl_two_len);
    if (pl_two < 0) {
        fatal_error("Error in syscall accept.", 3);
    }

コマンド ラインで自分のマシンの IP を指定するとserver_name、クライアントの が のような文字列に設定され151.51.xxx.xxx、ソケットがサーバーに接続できなくなります。また、使用し127.0.0.1ても同じ動作が示されるため、ドキュメントに次のように記載されていると思います。

関心のあるホスト名は nodename パラメーターに入ります。アドレスは、「www.example.com」などのホスト名か、IPv4 または IPv6 アドレス (文字列として渡される) のいずれかです。

冗談です。

私は何か間違ったことをしていますか?クライアントが IP アドレスを使用して接続するのを妨げているファイアウォールなどに問題がある可能性はありますか?

注:私はすでにこの問題をたくさん検索しており、使用getaddrinfoをまったく避けて を直接入力するように言う人もいますINADDR_ANYが、getaddrinfoドキュメントには as を渡すとアドレスが で埋めNULLられるはずであると記載されているため、なぜ使用する必要があるのか​​ わかりません新しい方法がこれを自動的に行うときの古い方法。nodenameINADDR_ANY

4

1 に答える 1

2

コメントに書かれているように、ルーターの背後にあるネットワークにあるサーバーに接続しようとしています。

127.0.0.1またはlocalhostオペレーティング システムのリダイレクトであり、ルーターを経由しません。それがあなたのために働いた理由です。

外部 IP アドレスを指定すると、接続はルーター経由で行われ、使用するポートはルーター構成で転送する必要があります。通常のホーム インターネット エンド ユーザー ルーターは、デフォルトで任意のポートからの着信接続をブロックします。

于 2013-05-04T11:20:16.220 に答える