【发布时间】:2018-01-18 19:11:56
【问题描述】:
我正在尝试创建一个 void mksockaddr(int af, int proto, char addr[], struct sockaddr* dst) 来创建一个 sockaddr 结构,这就是我所做的:
void sockaddr(int af, int port, char addr[], struct sockaddr* dst) {
if (af == AF_INET) {
struct sockaddr_in s;
s.sin_family = af;
s.sin_port = htons(port);
inet_pton(af, addr, &s.sin_addr);
memcpy(dst, &s, sizeof(s));
} else {
struct sockaddr_in6 s;
s.sin6_family = af;
s.sin6_port = htons(port);
s.sin6_flowinfo = 0;
inet_pton(af, addr, &s.sin6_addr);
memcpy(dst, &s, sizeof(s));
}
}
这似乎用AF_INET(IPv4)没有问题,我可以bind()没有任何问题,但是当我尝试使用AF_INET6时,bind()给我无效的参数。
这是我用来bind()的代码:
int sock_fd = socket(AF_INET6, SOCK_RAW, proto);
struct sockaddr sin;
sockaddr(AF_INET6, proto, src, &sin);
if(bind(sock_fd, &sin, sizeof(sin)) < 0) {
fprintf(stderr, "[ERR] can't bind socket: %s\n", strerror(errno));
exit(1);
} // got Invalid argument
但是,如果我自己构造一个sockaddr_in6,我可以bind() 就好了:
struct sockaddr_in6 sin;
sin.sin6_port = htons(proto);
sin.sin6_family = AF_INET6;
inet_pton(AF_INET6, src, &sin.sin6_addr);
if(bind(sock_fd, (struct sockaddr*) &sin, sizeof(sin)) < 0) {
fprintf(stderr, "[ERR] can't bind socket.\n");
exit(1);
} // work just fine
所以我将函数创建的sockaddr 转换回sockaddr_in6,我可以看到除了sin6_scope_id 之外的所有字段都相同。据我了解,sin6_scope_id 无关紧要,除非我处理的是链接本地 IPv6 地址。
我这里有什么遗漏吗?
【问题讨论】:
-
如果您正在执行的“工作正常”代码
htons(proto),我认为应该是htons(port),但我不知道为什么会成败。 -
你是如何使用这个功能的?特别是,你传递给
dst参数的是什么?请编辑您的问题,为每个支持的案例添加一个示例调用。 -
@JohnBollinger 查看第二个代码块,使用
sockaddr(AF_INET6, proto, src, &sin);调用。 -
您应该使用
getaddrinfo来为您处理 v4/v6 案例。