2013-05-04 12 views
5

私は小さなCクライアント/サーバーアプリケーションを作成していますが、外部IPアドレスを使用しているときは接続を確立できません。クライアントとサーバーの両方のためのコードは、クライアントが行う具体的には、hereから取られる:getaddrinfoを使用して外部IPを使用してサーバーに接続する方法は?

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_name151.51.xxx.xxxのような文字列に設定されていると、ソケットはサーバーに接続できません。あなたが興味を持っている

ホスト名は、ノード名 パラメータに行く:また127.0.0.1を使用すると、私はドキュメントが述べているときだと思います同じ動作を示しています。アドレスには、 "www.example.com"のようなホスト名、またはIPv4またはIPv6アドレス(文字列として渡される)のいずれかを指定できます。

ちょうど冗談です。

私は間違って何かしていますか?ファイアウォールなどでクライアントがIPアドレスを使用して接続できないような問題がありますか?

注:私はすでにこの問題のために多くのことを検索したと、一部の人々はまったくgetaddrinfoを使用して回避し、直接INADDR_ANYを埋めるために言うが、getaddrinfoドキュメントはnodenameとしてNULLを渡すと、すでにINADDR_ANYと住所を記入しなければならないと述べています新しいメソッドが自動的にこれを行う場合、古いメソッドを使用する必要があるのはわかりません。

+0

サーバー部分が期待通りに機能するには(接続を受け入れるために) 'listen()'と 'accept()'の呼び出しを追加する必要があります。第9.15章と第9.1章をお読みください。 – alk

+0

@alk私は明らかに 'listen'と' accept'を呼び出しています(そうでなければ、クライアントが 'localhost'を' server_name'として使用しているとサーバーはどうなりますか?)。とにかく質問に追加します。 – Bakuriu

+2

サーバはルータの後ろにありますか?必要なポートは開いているか転送していますか? – typ1232

答えて

1

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

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

外部IPアドレスを指定すると、ルータ経由で接続され、使用するポートはルータ設定で転送する必要があります。通常の家庭内インターネットエンドユーザールーターは、既定で任意のポートからの着信接続をブロックします。

関連する問題