最近阅读UNIX网络编程第四章时,书本末尾介绍了两个函数getsockname()和getpeername(),可以用于获取服务器端和客户端的IP地址与端口,原本很简单的两个函数,过一眼即明白函数的用法,但在实际编程测试中,却出现了一个让人意外的结果,这两个函数在第一个客户连接时解析出的IP地址和端口全部为0,出乎我的期望。而在后面的客户连接时,打印出的IP地址和端口却是正确的。
下面先给出客户端和服务端的代码:
客户端:
#include <netinet/in.h> #include <sys/socket.h> #include <unistd.h> #include <pton32> #include <iostream> int main(int argc, char const *argv[]) { int sockfd; sockaddr_in srvaddr; bzero(&srvaddr, sizeof(srvaddr)); srvaddr.sin_family = AF_INET; if (argc < 2) { std::cout << "usage:" << argv[0] << " <IP address>" << std::endl; return -1; } srvaddr.sin_addr = pton32(argv[1]); srvaddr.sin_port = htons(7777); sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (connect(sockfd, (sockaddr *)&srvaddr, sizeof(srvaddr)) != 0) { std::cout << "connect error,retry please."; throw; } char str[128] = {‘\0‘}; while ((read(sockfd, str, 127)) > 0) { std::cout << str << ‘ ‘; } std::cout << std::endl; close(sockfd); return 0; }
服务端:
#include <netinet/in.h> #include <sys/socket.h> #include <unistd.h> #include <pton32> #include <iostream> int main(int argc, char const *argv[]) { int listenfd, connfd; sockaddr_in cliaddr, srvaddr; bzero(&srvaddr, sizeof(srvaddr)); srvaddr.sin_family = AF_INET; srvaddr.sin_addr.s_addr = htonl(INADDR_ANY); srvaddr.sin_port = htons(7777); listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (bind(listenfd, (sockaddr *)&srvaddr, sizeof(srvaddr))) { std::cout << "bind failed." << std::endl; return -1; } if (listen(listenfd, 32)) { std::cout << "listen failed." << std::endl; return -1; } char str[128] = {‘\0‘}; bzero(&cliaddr, sizeof(cliaddr)); while (true) { socklen_t length = sizeof(cliaddr); connfd = accept(listenfd, (sockaddr *)&cliaddr, &length); sockaddr_in local, peer; socklen_t local_len, peer_len; bzero(&local, sizeof(local)); bzero(&peer, sizeof(srvaddr)); getsockname(connfd, (sockaddr *)&local, &local_len); getpeername(connfd, (sockaddr *)&peer, &peer_len); char buff_local[64] = {‘\0‘}, buff_peer[64] = {‘\0‘}; if (inet_ntop(AF_INET, (void *)&local.sin_addr, buff_local, 63)) { std::cout << buff_local << std::endl; } if (inet_ntop(AF_INET, (void *)&peer.sin_addr, buff_peer, 63)) { std::cout << buff_peer << std::endl; } write(connfd, str, 127); close(connfd); } return 0; }
其中的pton32头文件是我个人自定义的头文件,用于转换IP地址,定义如下:
#include <netinet/in.h> #include <arpa/inet.h> #include <strings.h> #include <iostream> in_addr pton32(const char *str) { in_addr s_addr; try { if (1 == inet_pton(AF_INET, str, &s_addr)) return s_addr; else throw false; } catch (bool b) { std::cout << "convert failed." << std::endl; } bzero(&s_addr, sizeof(s_addr)); return s_addr; }
。
时间: 2024-10-14 15:17:18