版权声明:转载请标明出处。
本篇为记录linux socket支持ipv6的学习笔记。
udp服务端程序:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
int main(int argc, char **argv)
{
struct sockaddr_in6 s_addr;
struct sockaddr_in6 c_addr;
int sock;
socklen_t addr_len;
int len;
char buff[128];
char buf_ip[128];
if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(errno);
} else
printf("create socket.\n\r");
memset(&s_addr, 0, sizeof(struct sockaddr_in6));
s_addr.sin6_family = AF_INET6;
if (argv[2])
s_addr.sin6_port = htons(atoi(argv[2]));
else
s_addr.sin6_port = htons(4444);
if (argv[1])
inet_pton(AF_INET6, argv[1], &s_addr.sin6_addr);
else
s_addr.sin6_addr = in6addr_any;
s_addr.sin6_port = htons(12344);
s_addr.sin6_addr = in6addr_any;
int on = 1;
//if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0)
//{
// perror("setsockopt");
// return -1;
//}
if ((bind(sock, (struct sockaddr *) &s_addr, sizeof(s_addr))) == -1) {
perror("bind");
exit(errno);
} else
printf("bind address to socket.\n\r");
addr_len = sizeof(c_addr);
while (1) {
len = recvfrom(sock, buff, sizeof(buff) - 1, 0,
(struct sockaddr *) &c_addr, &addr_len);
if (len < 0) {
perror("recvfrom");
exit(errno);
}
buff[len] = '\0';
printf("receive from %s: buffer:%s\n\r",
inet_ntop(AF_INET6, &c_addr.sin6_addr, buf_ip, sizeof(buf_ip)),
buff);
}
return 0;
}
upd客户端程序:
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
static char src[] = "fe80::20c:29ff:fed2:4aff";
static char dst[] = "fe80::20c:29ff:fef4:40f";
void main(int argc, char **argv)
{
int udp6_socket, ret, ttl, on, addr_len;
struct sockaddr_in6 saddr;
struct sockaddr_in6 daddr;
memset(&daddr,0,sizeof(struct sockaddr_in6));
char buffer[] = "Hello World6";
if ((inet_pton(AF_INET6, (char *)&dst[0], &daddr.sin6_addr)) != 1)
{
printf("invalid ipv6 addr \r\n");
return ;
}
addr_len = sizeof(struct sockaddr_in6);
daddr.sin6_family = AF_INET6;
daddr.sin6_port = htons(12345);
/* 创建IPv6套接字,IPv6使用AF_INET6 */
udp6_socket = socket(AF_INET6, SOCK_DGRAM, 0);
if (udp6_socket == -1)
{
printf("create udp6_socket fail\r\n");
return;
}
// if (setsockopt(udp6_socket, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0)
// {
// perror("setsockopt");
// return ;
// }
/* 发送 */
ret = sendto(udp6_socket, &buffer[0], sizeof(buffer), 0, (struct sockaddr *)&daddr, addr_len);
if (ret > 0){
printf("udp6 send %d bytes success \r\n", ret);
}else{
perror("send error");
}
/* 关闭套接字 */
close(udp6_socket);
return;
}
与ipv6的tcp socket相比,upd不需要绑定网卡就可以进行通信了。
注意:记得设置ipv6防火墙ip6tables,把端口的权限打开,否则可能两台不同的机器会无法通信。