c - 绑定到 INADDR_LOOPBACK 时“无法分配请求的地址”,但 INADDR_ANY 有效
问题描述
注意:我找到了研究这个问题的解决方案。下一个犯这个错误的人希望在花费大量时间之前发现这个问题。
我一直在尝试在 Linux 系统上实现 TCP 服务器。问题是我收到了一条非常通用的错误消息,它没有揭示问题的原因:
$ gcc -Wall -Wextra main.c
$ ./a.out
bind: Cannot assign requested address
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1) {
fprintf(stderr, "socket: %s\n", strerror(errno));
return EXIT_FAILURE;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = 8080;
addr.sin_addr.s_addr = INADDR_LOOPBACK;
if(bind(sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) {
fprintf(stderr, "bind: %s\n", strerror(errno));
return EXIT_FAILURE;
}
if(close(sockfd) != 0) {
fprintf(stderr, "close: %s\n", strerror(errno));
return EXIT_FAILURE;
}
}
这个网站上有无数个问题描述了类似的问题,但这里的关键是当我尝试绑定到INADDR_ANY
而不是INADDR_LOOPBACK
. 我发现了一些有这个问题的问题,但反过来有点奇怪。
此错误消息的可能原因是什么?
解决方案
我一直在分配端口和地址错误:
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = 8080;
addr.sin_addr.s_addr = INADDR_LOOPBACK;
应该
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
htons
代表“host to network short”和htonl
代表“host to network long”,指的是地址和端口编码的字节顺序。
INADDR_ANY
是地址0.0.0.0
,字节顺序在这里无关紧要。是被错误理解为INADDR_LOOPBACK
的地址。127.0.0.1
1.0.0.127
推荐阅读
- reactjs - Meteorjs 反应宇宙:i18n
- reactjs - react-grid-layout 没有显示我通过他的布局
- r - R 依赖包似乎在包中不可用
- apache-spark - PYSAPRK python java.lang.NoSuchMethodError:net.jpountz.lz4.LZ4BlockInputStream。
(Ljava/io/InputStream;Z)V - algorithm - 为什么朴素素数测试算法不是多项式
- android - 从互联网加载数据后如何管理片段`onCreateView()`
- ruby-on-rails - 连接表中的多个外键
- azure - 如何获取访问令牌以启动或关闭 azure 经典门户上的 VM?
- php - 通过 shell_exec() 在后台执行命令
- javascript - 如何将字典从 javascript 传递到烧瓶?