如今,随着网络的日益普及,IPv4地址数量相对于与日俱增的网络设备而言,简直太稀缺了,已经远远无法满足日常需求,因此出现了IPv6协议,并开始逐渐向IPv6进行过渡。在如今的过渡阶段中,网络环境中同时存在IPv4网络和IPv6网络,因此开发软件时通常要求支持双栈的功能

同时监控双栈(IPv4栈、IPv6栈)下的指定端口号实现上也比较简单,分别创建两个套接字:

  • 一个用来监听IPv4端口
  • 一个用来监听IPv6端口

只是这里面有一个需要注意的地方:

创建两个UDP套接字,分别监听IPv4,IPv6端口,不存在特别的问题。但是TCP却不同,如果先创建并绑定IPv4的端口,则另一个套接字无法直接绑定IPv6的相同端口。会提示如下信息:

bind failed: : Address already in use

此时需要设置IPv6套接字的高级选项(IPPROTO_IPV6)方可以进行绑定和监听:

static const int on = 1;
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,(const void *)&on, sizeof(on))

UDP无需此项参数设置,具体原因未知。

完整代码实现如下(包括udp, tcp监控双栈代码):

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>int creatSocketUdp(char *ip, short port)
{static const int on = 1;int fd;struct sockaddr_in server;if ((fd = socket(AF_INET, SOCK_DGRAM, 0))<0){perror("creatSocketUdp_v6 create socket failed: ");return -1;}else if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on))<0){perror("creatSocketUdp_v6 set REUSEADDR failed: ");return -1;}bzero(&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(port);server.sin_addr.s_addr = htonl(INADDR_ANY);int ret = bind(fd, (struct sockaddr *)&server, sizeof(server));if (ret != 0){perror("creatSocketUdp_v6 bind failed: ");return -1;}return fd;
}int creatSocketUdp_v6(char *ip, short port)
{static const int on = 1;int fd;struct sockaddr_in6 server;if ((fd = socket(AF_INET6, SOCK_DGRAM, 0))<0){perror("creatSocketUdp_v6 create socket failed: ");return -1;}else if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on))<0){perror("creatSocketUdp_v6 set REUSEADDR failed: ");return -1;
/*  }else if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,(const void *)&on, sizeof(on))<0){perror("creatSocketUdp_v6 set REUSEADDR failed: ");return -1; */}bzero(&server, sizeof(server));server.sin6_family = AF_INET6;server.sin6_addr = in6addr_any;server.sin6_port = htons(port);int ret = bind(fd, (struct sockaddr *)&server, sizeof(server));if (ret != 0){perror("creatSocketUdp_v6 bind failed: ");return -1;}return fd;
}int creatSocketTcp(char *ip, short port)
{static const int on = 1;int fd;struct sockaddr_in server;if ((fd = socket(AF_INET, SOCK_STREAM, 0))<0){perror("creatSocketTcp create socket failed: ");return -1;}else if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on))<0){perror("creatSocketTcp set REUSEADDR failed: ");return -1;}bzero(&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(port);server.sin_addr.s_addr = htonl(INADDR_ANY);int ret = bind(fd, (struct sockaddr *)&server, sizeof(server));if (ret != 0){perror("creatSocketTcp bind failed: ");return -1;}if (listen(fd, 5)<0){perror("creatSocketTcp listen failed: ");return -1;}return fd;
}int creatSocketTcp_v6(char *ip, short port)
{static const int on = 1;int fd;struct sockaddr_in6 server;if ((fd = socket(AF_INET6, SOCK_STREAM, 0))<0){perror("creatSocketTcp_v6 create socket failed: ");return -1;}else if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on))<0){perror("creatSocketTcp_v6 set REUSEADDR failed: ");return -1;}else if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,(const void *)&on, sizeof(on))<0){perror("creatSocketTcp_v6 set REUSEADDR failed: ");return -1; }bzero(&server, sizeof(server));server.sin6_family = AF_INET6;server.sin6_addr = in6addr_any;server.sin6_port = htons(port);int ret = bind(fd, (struct sockaddr *)&server, sizeof(server));if (ret != 0){perror("creatSocketTcp_v6 bind failed: ");return -1;}if (listen(fd, 5)<0){perror("creatSocketTcp_v6 listen failed: ");return -1;} return fd;
}void main(int argc, char** argv)
{char buf[1024] = {0};int buflen = 0;int clientLen = 0;struct sockaddr client;int ret = 0;int fd ;int fd6;if (argc != 2){printf("Usage: ./a.out tcp|udp\n");return ;}else if(strstr(argv[1],"udp")){fd = creatSocketUdp(NULL, 8080);if(fd < 0){printf("%s:%d error\n", __func__, __LINE__);return ;}fd6 = creatSocketUdp_v6(NULL, 8080);if(fd < 0){printf("%s:%d error\n", __func__, __LINE__);return ;}}else if(strstr(argv[1],"tcp")){fd = creatSocketTcp(NULL, 8080);if(fd < 0){printf("%s:%d error\n", __func__, __LINE__);return ;}fd6 = creatSocketTcp_v6(NULL, 8080);if(fd6 < 0){printf("%s:%d error\n", __func__, __LINE__);return ;}}else{printf("Usage: ./a.out tcp|udp\n");return ;}bzero(&client, sizeof(client));fd_set readfds;int maxFD = 0;struct timeval timeVal;while(1){FD_ZERO(&readfds);FD_SET(fd, &readfds);FD_SET(fd, &readfds);maxFD = fd6 > fd ? fd6:fd;timeVal.tv_sec = 1;timeVal.tv_usec = 0;ret = select(maxFD, &readfds,NULL,NULL,&timeVal);if (ret == 0){printf("【Timeout!!!】\n");continue;}else if (ret < 0){perror("Whack Fucking error??? :");break;}else{if (FD_ISSET(fd, &readfds)){buflen = recvfrom(fd, buf, 1024, 0, (struct sockaddr *)&client, &clientLen);if(buflen>0){printf("【recv packet v4】: %s\n", buf);sendto(fd, buf, buflen, 0, (struct sockaddr *)&client, clientLen);}}else if(FD_ISSET(fd, &readfds)){buflen = recvfrom(fd, buf, 1024, 0, (struct sockaddr *)&client, &clientLen);if(buflen>0){printf("【recv packet v6】: %s\n", buf);sendto(fd, buf, buflen, 0, (struct sockaddr *)&client, clientLen);}}}}}

监控IPv4和IPv6下的相同端口相关推荐

  1. 记录一次nginx升级,支持ipv4和ipv6访问https

    项目要求,需要让现有网站项目支持https,并同时支持ipv6访问,经过分析,现在nginx版本较老,所以决定升级nignx,并且同步配置https和ipv6. 升级准备 服务器网络环境需要支持ipv ...

  2. teredo实现ipv4公网环境下接入ipv6

    teredo实现ipv4公网环境下接入ipv6 系统:macOS High Sierra 10.13.3 测试成功 软件下载 下载安装Miredo http://www.deepdarc.com/mi ...

  3. Linux的ipv6不监听端口,netstat查看服务端口监听在ipv6但是通过ipv4地址可正常访问...

    在Linux系统中,会发现一个有趣的现象,通过 netstat 查看监听的服务端口时,发现有些服务 Proto(protocol协议) 项只显示了 tcp6(代表监听服务端口在IPv6协议), 没有 ...

  4. (转)网络编程:Socket编程从IPv4转向IPv6支持

    目前运行主流的IT系统中,用于解决分布式系统内部模块及不同的系统间通信的一种主要的解决方案就是使用套接字Socket来开发应用.由于当前大部分正在运行的IT系统中使用套接字Socket开发环境基本上都 ...

  5. 当P4遇见NAT64,UCloud如何快速从IPv4向IPv6演进?

    IPv4发展到今天已存在着诸多缺陷,比如地址枯竭.安全和服务质量难以保证.路由膨胀等,这些问题将极大制约云计算等相关IT行业的发展.IPv6以其更大的地址空间.更高的安全性等特点,能够很好的解决IPv ...

  6. 【计算机网络】网络层 : 总结 ( 功能 | 数据交换 | IP 数据报 | IPv4 地址 | IPv6 地址 | 路由选择协议 | 路由算法 )★★★

    文章目录 一.网络层功能 二.数据交换方式 ★ 三.IP 数据报 ★ 四. IPv4 地址 ★★ 1 . IP 地址 发展 : 2 . 分类 IP 地址 3 . NAT 转换 4 . 子网划分 5 . ...

  7. python 编写一个函数来验证输入的字符串是否是有效的 IPv4 或 IPv6 地址_产品 | 工信部发声IPv6即将部署,你的路由需要更换吗?...

    提到说话算数不得不表扬一下工信部,从最早的"提速降费"到现在的"携号转网",每一件事情都办的有条不紊,件件落实到咱们老百姓的生活上. 最近两年工信部都在忙一件大 ...

  8. IPv6下网络编程实例

    一.TCP socket ipv6与ipv4的区别 服务器端源代码如下: [cpp] view plain copy #include <stdio.h> #include <std ...

  9. IPV4与IPV6的区别(史上最详细)

    IPV4与IPV6的区别(史上最详细) 描述 IPv4 IPv6 地址 长度为 32 位(4 个字节).地址由网络和主机部分组成,这取决于地址类.根据地址的前几位,可定义各种地址类:A.B.C.D 或 ...

最新文章

  1. cacti被监控机上snmp的安装及报错解决
  2. hdu 3863 No Gambling (不会证明,但是是对的,,)
  3. 高颜值可定制在线作图工具-第二版
  4. 微信小程序种利用轮播图实现tab栏切换
  5. SPOJ NSUBSTR(后缀自动机)
  6. linux进程线程协程的区别,进程和线程、协程的区别
  7. 如何在HTMl网页中插入百度地图
  8. 手输Unicode字符的方法
  9. 杀毒软件 对应的进程名称
  10. 几款引擎比较 BigWorld Unreal CryEngine等
  11. wifi工具iw常用操作
  12. Altium Designer -- 精心总结
  13. 17 款程序员神级 Chrome 插件,爱了爱了!
  14. Urllib2库+正则爬取内涵段子
  15. 概率计算机在线,高斯正态分布(概率)计算公式与在线计算器_三贝计算网_23bei.com...
  16. 当时我就哭了!中国首个火星探测器天问一号发射成功!
  17. STL--函数对象学习
  18. 硕士论文答辩事宜总结
  19. 零售药店计算机操作内容培训,零售药店gsp培训计划.doc
  20. Qt 之 模仿 QQ登陆界面——旋转窗口篇

热门文章

  1. isp是什么意思,如何选择并确定ISP商
  2. 查看本机 ssh 公钥,生成公钥
  3. 电源模块中CNT、TRM和SENSE引脚
  4. 快速查询德邦物流信息,并标记未签收单号
  5. 基于索引的SQL语句优化之降龙十八掌
  6. python回车符是什么_python换行符是什么?
  7. c语言数组赋值可以用scanf吗,二维数组怎么赋值 用scanf给二维数组赋值
  8. unity击败计数_关于“击败”团队目标的思考
  9. 音视频学习之rtsp学习rtp协议的理解(rtp)
  10. 百度云bae安装discuz论坛教程