작은 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_name
은 151.51.xxx.xxx
과 같은 문자열로 설정되고 소켓은 서버에 연결할 수 없습니다. 관심있는
호스트 이름이 노드 이름 매개 변수에 간다 : 또한
127.0.0.1
를 사용하는 것은 나를 설명서를 언급 할 때 생각하게 동일한 동작을 보여줍니다. 주소는 "www.example.com"과 같은 호스트 이름이거나 IPv4 또는 IPv6 주소 (문자열로 전달됨) 일 수 있습니다.
그냥 농담입니다.
내가 잘못하고 있습니까? 방화벽 등에서 클라이언트가 IP 주소를 사용하여 연결하지 못하게하는 데 몇 가지 문제가있을 수 있습니까?
참고 : 난 이미이 문제에 대해 많이 검색 한 어떤 사람들은 전혀 getaddrinfo
을 사용하지 않도록 직접 INADDR_ANY
채우기 위해 말을하지만, getaddrinfo
문서는 통과 NULL
nodename
로 이미 INADDR_ANY
과 주소를 작성해야한다고 그래서 새로운 방법이 이것을 자동으로 수행 할 때 이전 방법을 사용해야하는 이유는 알 수 없습니다.
서버 부분이 예상대로 작동하려면 (연결을 수락 할 수 있도록)'listen()'및'accept()'에 대한 호출을 추가해야합니다. 9.15 장과 9.1 장을 읽으십시오. – alk
@alk 클라이언트가'localhost'를'server_name'로 사용한다면 서버가 어떻게 작동 할까?)'listen'과'accept'를 호출하는 것은 분명합니다. 어쨌든 질문에 추가하겠습니다. – Bakuriu
서버가 라우터 뒤에 있습니까? 필요한 포트를 열었거나 전달 했습니까? – typ1232