2013-05-04 3 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 문서는 통과 NULLnodename로 이미 INADDR_ANY과 주소를 작성해야한다고 그래서 새로운 방법이 이것을 자동으로 수행 할 때 이전 방법을 사용해야하는 이유는 알 수 없습니다.

+0

서버 부분이 예상대로 작동하려면 (연결을 수락 할 수 있도록)'listen()'및'accept()'에 대한 호출을 추가해야합니다. 9.15 장과 9.1 장을 읽으십시오. – alk

+0

@alk 클라이언트가'localhost'를'server_name'로 사용한다면 서버가 어떻게 작동 할까?)'listen'과'accept'를 호출하는 것은 분명합니다. 어쨌든 질문에 추가하겠습니다. – Bakuriu

+2

서버가 라우터 뒤에 있습니까? 필요한 포트를 열었거나 전달 했습니까? – typ1232

답변

1

라우터에있는 네트워크에있는 서버에 연결하려고하면 코멘트에 기록됩니다.

127.0.0.1 또는 localhost은 운영 체제의 리디렉션이며 라우터를 거치지 않습니다. 그것이 당신을 위해 일한 이유입니다.

외부 IP 주소를 지정하면 라우터를 통해 연결되며 사용하는 포트는 라우터 구성에서 전달되어야합니다. 일반 가정 인터넷 최종 사용자 라우터는 기본적으로 모든 포트에서 들어오는 연결을 차단합니다.