我正在編寫一個小型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 2013-05-04 10:22:57
@alk我明顯有調用'listen'和'accept'(否則,如果客戶端使用'localhost'作爲'server_name',服務器是如何工作的?)。無論如何,我會將它們添加到問題中。 – Bakuriu 2013-05-04 10:34:10
路由器後面的服務器?所需的端口是否打開或轉發? – typ1232 2013-05-04 10:45:05