【发布时间】:2013-05-04 09:23:44
【问题描述】:
我正在编写一个小型 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 显示相同的行为,这让我认为当文档状态:
您感兴趣的主机名放在节点名中 范围。地址可以是主机名,例如 “www.example.com”,或 IPv4 或 IPv6 地址(作为字符串传递)。
这只是开玩笑。
我做错了吗?会不会是防火墙等问题导致客户端无法使用 IP 地址进行连接?
注意:我已经为此问题进行了很多搜索,有些人说要避免使用getaddrinfo,直接填写INADDR_ANY,但getaddrinfo 文档指出将NULL 传递为@987654331 @应该已经用INADDR_ANY填充了地址,所以我不明白为什么当新方法自动这样做时我应该使用旧方法。
【问题讨论】:
-
要使服务器部分按预期工作(能够接受连接),您必须添加对
listen()和accept()的调用。您可能想阅读第 9.15 章和第 9.1 章。 -
@alk 我显然确实调用了
listen和accept(否则,如果客户端使用localhost作为server_name,服务器如何工作?)。无论如何,我都会将它们添加到问题中。 -
服务器在路由器后面吗?是否打开或转发了所需的端口?
-
一些较旧的“共享互联网”盒子无法完成您似乎想要做的事情。也就是说,如果您设置了端口转发,则只有在您尝试从本地网络之外的机器连接时它才会起作用。
-
@typ1232 我有路由器,我认为它可能会阻止与大多数端口的连接......我仍然不明白为什么传递
127.0.0.1与传递localhost不同。无论如何,问题似乎不是代码而是路由器配置。 @Sudhee 不,如果我使用localhost它可以工作,如果我使用 anything 否则它不起作用。
标签: c sockets getaddrinfo