C++ IPv4与IPv6的兼容编码
来源:互联网 发布:济宁天拓网络 编辑:程序博客网 时间:2024/05/16 10:12
这里不再对IPv6 socket相关编程的基础知识进行讲解,只提供一个IP协议无关的服务端和客户端的代码,仅供参考。
服务端代码:
#include <iostream>#include <string>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netdb.h>#include <errno.h>#include <time.h>using namespace std;int tcp_listen(const char *host, const char *service, const int listen_num = 5){int listenfd, ret;const int on = 1;struct addrinfo hints, *res, *ressave;bzero(&hints, sizeof(hints));hints.ai_flags = AI_PASSIVE;hints.ai_family = AF_UNSPEC;hints.ai_socktype = SOCK_STREAM;hints.ai_protocol = IPPROTO_IP;if (0 != (ret = getaddrinfo(host, service, &hints, &res))){cout << "getaddrinfo error: " << gai_strerror(ret) << endl;return -1;}ressave = res;while(NULL != res){if (-1 == (listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol))){cout << "create socket error: " << strerror(errno) << endl;res = res->ai_next;continue;}if (-1 == setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))){cout << "setsockopt error: " << strerror(errno) << endl;close(listenfd);res = res->ai_next;continue;}if (-1 == bind(listenfd, res->ai_addr, res->ai_addrlen)){cout << "bind error: " << strerror(errno) << endl; close(listenfd); res = res->ai_next; continue;}if (-1 == listen(listenfd, listen_num)){cout << "listen error: " << strerror(errno) << endl; close(listenfd); res = res->ai_next; continue;}break;}freeaddrinfo(ressave);if (NULL == res)return -1;return listenfd;}int get_addrinfo(const struct sockaddr *addr, string &ip, in_port_t &port){void *numeric_addr = NULL;char addr_buff[INET6_ADDRSTRLEN];if (AF_INET == addr->sa_family){numeric_addr = &((struct sockaddr_in*)addr)->sin_addr;port = ntohs(((struct sockaddr_in*)addr)->sin_port);}else if (AF_INET6 == addr->sa_family){numeric_addr = &((struct sockaddr_in6*)addr)->sin6_addr;port = ntohs(((struct sockaddr_in6*)addr)->sin6_port);}else{return -1;}if (NULL != inet_ntop(addr->sa_family, numeric_addr, addr_buff, sizeof(addr_buff)))ip = addr_buff;elsereturn -1;return 0;}int main(int argc, char *argv[]){int listenfd, connfd;struct sockaddr_storage cliaddr;socklen_t len = sizeof(cliaddr);time_t now;char buff[128];if (2 == argc) //指定端口listenfd = tcp_listen(NULL, argv[1]);else if (3 == argc) //指定本地IP和端口listenfd = tcp_listen(argv[1], argv[2]);else{ cout << "usage: " << argv[0] << " [<hostname/ipaddress>] <service/port>" << endl;return -1;}if (listenfd < 0){cout << "call tcp_listen error" << endl;return -1;}while (true){connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &len);string ip = "";in_port_t port = 0;get_addrinfo((struct sockaddr*)&cliaddr, ip, port);cout << "client " << ip << "|" << port << " login" << endl;now = time(NULL);snprintf(buff, sizeof(buff) - 1, "%.24s", ctime(&now));write(connfd, buff, strlen(buff));close(connfd);}close(listenfd);return 0;}
#include <iostream>#include <string>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netdb.h>#include <errno.h>#include <time.h>using namespace std;int tcp_connect(const char *host, const char *service){int sockfd, ret;struct addrinfo hints, *res, *ressave;bzero(&hints, sizeof(hints));hints.ai_family = AF_UNSPEC;hints.ai_socktype = SOCK_STREAM;hints.ai_protocol = IPPROTO_IP;if (0 != (ret = getaddrinfo(host, service, &hints, &res))){cout << "getaddrinfo error: " << gai_strerror(ret) << endl;return -1;}ressave = res;while (NULL != res){if (-1 == (sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol))) { cout << "create socket error: " << strerror(errno) << endl; res = res->ai_next; continue; }if (-1 == connect(sockfd, res->ai_addr, res->ai_addrlen)){cout << "connect error: " << strerror(errno) << endl; close(sockfd);res = res->ai_next; continue;}break;}freeaddrinfo(ressave);if (NULL == res)return -1;return sockfd;}int main(int argc, char *argv[]){int sockfd, n;char buff[128];struct sockaddr_storage cliaddr;if (3 != argc){cout << "usage: " << argv[0] << " <hostname/ipaddress> <service/port>" << endl;return -1;}sockfd = tcp_connect(argv[1], argv[2]);if (sockfd < 0){cout << "call tcp_connect error" << endl;return -1;}bzero(buff, sizeof(buff));while ((n = read(sockfd, buff, sizeof(buff) - 1) > 0)){cout << buff << endl;bzero(buff, sizeof(buff));}close(sockfd);return 0;}
编译:
g++ daytimesrv.cpp -o daytimesrv
g++ daytimecli.cpp -o daytimecli
运行举例:
服务端运行情况:
客户端运行情况:
以上客户端的请求与服务端的输出一一对应,客户端可以尝试用不同的IP去连接,然后观察服务端的输出,有助于理解底层的交互过程。
1 0
- C++ IPv4与IPv6的兼容编码
- C++ IPv4与IPv6的兼容编码
- C++ IPv4与IPv6的兼容编码
- IOS socket 兼容IPV4与IPV6
- IPv4与IPv6的区别
- IPV4与IPV6的区别
- ipv6 ipv4的socket编码的区别
- IPv6为啥无法兼容IPv4?
- IPV4与IPV6的联系与区别
- 客户端底层 Socket 实现IPV4 IPV6网络环境的兼容
- IPv6报头与IPv4报头的区别
- IPv4与IPv6的区别是什么
- IPv4与IPv6的互操作性
- ipv6与ipv4的js正则判断
- 计算机网络—IPv4与IPv6 的区别
- TCP socket ipv6与ipv4的区别
- IPv4与IPv6的区别是什么?
- IPv4与IPv6的互操作性
- Linux常用开发环境安装
- [Android问答] px、dp和sp,这些单位有什么区别?
- 45 个非常有用的 Oracle 查询语句
- android intent中的action data Category、Extras的重要属性
- 欧拉回路,欧拉路
- C++ IPv4与IPv6的兼容编码
- 技术大局观,学习路线
- 状态模式的实例学习
- Repo 详解
- poj 1458&poj 1159 最长公共子序列LCS
- oracle表空间查询和表数据量查询
- 启动关闭Activity
- Unity3D实现点击物体旋转和拖动
- 利用PDFBox读取pdf文件文本