都江堰市建设局网站,网站首页加浮动窗口,wordpress和网站区别,电子商务网页设计是什么https://www.tuicool.com/articles/V3Aveygetsockname和getpeername函数
getsockname函数用于获取与某个套接字关联的本地协议地址 getpeername函数用于获取与某个套接字关联的外地协议地址
定义如下#xff1a;[cpp] view plaincopy#includesys/socket.h int gets…https://www.tuicool.com/articles/V3Aveygetsockname和getpeername函数
getsockname函数用于获取与某个套接字关联的本地协议地址 getpeername函数用于获取与某个套接字关联的外地协议地址
定义如下[cpp] view plaincopy#includesys/socket.h int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen); int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen); 对于这两个函数如果函数调用成功则返回0如果调用出错则返回-1。
使用这两个函数我们可以通过套接字描述符来获取自己的IP地址和连接对端的IP地址如在未调用bind函数的TCP客户端程序上可以通过调用getsockname()函数获取由内核赋予该连接的本地IP地址和本地端口号还可以在TCP的服务器端accept成功后通过getpeername()函数来获取当前连接的客户端的IP地址和端口号。
如下面的客户端-服务器程序
服务器端代码[cpp] view plaincopy/*服务器端*/ #define MAXLINE 4096 #define PORT 6563 #define LISTENQ 1024 #includestdio.h #includesys/socket.h #includenetinet/in.h #includeunistd.h #includestring.h #includearpa/inet.h int main() { int listenfd, connfd; struct sockaddr_in servaddr;//服务器绑定的地址 struct sockaddr_in listendAddr, connectedAddr, peerAddr;//分别表示监听的地址连接的本地地址连接的对端地址 int listendAddrLen, connectedAddrLen, peerLen; char ipAddr[INET_ADDRSTRLEN];//保存点分十进制的地址 listenfd socket(AF_INET, SOCK_STREAM, 0); memset(servaddr, 0, sizeof(servaddr)); servaddr.sin_family AF_INET; servaddr.sin_addr.s_addr htonl(INADDR_ANY); servaddr.sin_port htons(PORT); bind(listenfd, (struct sockaddr*)servaddr, sizeof(servaddr));//服务器端绑定地址 listen(listenfd, LISTENQ); listendAddrLen sizeof(listendAddr); getsockname(listenfd, (struct sockaddr *)listendAddr, listendAddrLen);//获取监听的地址和端口 printf(listen address %s:%d\n, inet_ntoa(listendAddr.sin_addr), ntohs(listendAddr.sin_port)); while(1) { connfd accept(listenfd, (struct sockaddr *)NULL, NULL); connectedAddrLen sizeof(connectedAddr); getsockname(connfd, (struct sockaddr *)connectedAddr, connectedAddrLen);//获取connfd表示的连接上的本地地址 printf(connected server address %s:%d\n, inet_ntoa(connectedAddr.sin_addr), ntohs(connectedAddr.sin_port)); getpeername(connfd, (struct sockaddr *)peerAddr, peerLen); //获取connfd表示的连接上的对端地址 printf(connected peer address %s:%d\n, inet_ntop(AF_INET, peerAddr.sin_addr, ipAddr, sizeof(ipAddr)), ntohs(peerAddr.sin_port)); } return 0; } 上面的代码中在调用listen函数之后就获取监听套接字描述符对应的本地地址在accept()函数后由于accept返回了一个套接字描述符connfd用于表示该连接所以可以对这个connfd调用getsockname函数和getpeername函数分别获取内核赋予该连接的本地IP地址和连接的对端地址。
客户端代码[cpp] view plaincopy/*客户端*/ #define PORT 6563 #includestdio.h #includesys/socket.h #includenetinet/in.h #includeunistd.h #includestring.h #includearpa/inet.h int main(int argc, char **argv) { struct sockaddr_in servaddr;//服务器端地址 struct sockaddr_in clientAddr;//客户端地址 int sockfd; int clientAddrLen sizeof(clientAddr); char ipAddress[INET_ADDRSTRLEN];//保存点分十进制的ip地址 if(argc 2) { printf(parameter error); } sockfd socket(AF_INET, SOCK_STREAM, 0); memset(servaddr, 0, sizeof(servaddr)); servaddr.sin_family AF_INET; servaddr.sin_port htons(PORT); if(inet_pton(AF_INET, argv[1], servaddr.sin_addr) 0) { printf(server address error\n);//地址参数不合法 } connect(sockfd, (struct sockaddr *)servaddr, sizeof(servaddr));//向服务器端发起连接请求 getsockname(sockfd, (struct sockaddr*)clientAddr, clientAddrLen);//获取sockfd表示的连接上的本地地址 printf(client:client ddress %s:%d\n, inet_ntop(AF_INET, clientAddr.sin_addr, ipAddress, sizeof(ipAddress)), ntohs(clientAddr.sin_port)); return 0; } 在客户端的代码中调用connect函数后即可调用getsockname来获连接上的本地地址。
代码的运行结果如下
服务区端输出客户端输出从上面的代码中可以看到服务器端listenfd套接字描述符对应的地址即为绑定的通配IP地址和指定的端口而connfd套接字描述符对应的连接的服务器端的地址为内核赋予的地址和用户指定的端口。
上面的客户端与服务器端的代码中使用了函数inet_ntoainet_pton对32位的地址进行转换其中inet_ntoa是较老的函数与它一起的还有函数inet_addr和inet_ntoa这三个函数的定义如下[cpp] view plaincopy#includearpa/inet.h int inet_aton(const char *strptr, struct in_addr *addrptr); in_addr_t inet_addr(const char *strptr); char *inet_ntoa(struct in_addr inaddr); inet_aton与inet_addr函数的功能类似都是将点分十进制的字符串表示的IP地址转换成32位的网络字节序的IPv4地址。
inet_ntoa函数将32位的网络字节序的IPv4地址转换成点分十进制的字符串表示的IP地址inet_addr函数已被废弃并且这三个函数只针对IPv4地址有效在点分十进制数串和32位的网络字节序二进制值间进行转换如果要对于IPv4和IPv6都适用那么使用下面两个函数[cpp] view plaincopy#includearpa/inet.h int inet_pton(int family, const char *strptr, void *addrptr); const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len); 函数中的p和n分别代表表达式(presentation)和数值(numeric)
所以inet_pton函数将strptr指针所指的字符串转换为网络地址(IPv4和IPv6)再将地址保存到addrptr指向的结构体中inet_ntop将网络地址转为字符串表示的地址结果存放在strptr中len参数是strptr的大小。这两个函数支持IPv4和IPv6所以需要通过参数family来指定当前要转换的是IPv4地址还是IPv6地址。Reference
《UNIX网络编程 卷1套接字联网API第3版》