写一个 socket绑定iPv4和ipv6 源码
时间: 2023-03-25 16:00:45 浏览: 133
IPV4与IPV6兼容的socket编程
以下是一个简单的示例代码,用于在同一个 socket 上绑定 IPv4 和 IPv6 地址:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]) {
int sockfd, status;
struct addrinfo hints, *res, *p;
char ipstr[INET6_ADDRSTRLEN];
memset(&hints, , sizeof hints);
hints.ai_family = AF_UNSPEC; // IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
if ((status = getaddrinfo("localhost", "808", &hints, &res)) != ) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
// loop through all the results and bind to the first we can
for (p = res; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
perror("socket");
continue;
}
// set socket options to allow both IPv4 and IPv6
int yes = 1;
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) == -1) {
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "failed to bind socket\n");
exit(1);
}
// convert the IP address to a string and print it
void *addr;
if (p->ai_family == AF_INET) {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
} else {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
}
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
printf("bound to %s\n", ipstr);
freeaddrinfo(res); // free the linked list
return ;
}
```
这个示例代码使用了 `getaddrinfo()` 函数来获取一个或多个与指定主机名和服务名匹配的地址信息。然后,它循环遍历这些地址信息,尝试在每个地址上绑定一个 socket。在绑定之前,它还设置了一个 socket 选项,以允许同时支持 IPv4 和 IPv6。最后,它将绑定的 IP 地址转换为字符串,并打印出来。
阅读全文