getsockname函数用于获取与某个套接字关联的本地协议地址
getpeername函数用于获取与某个套接字关联的外地协议地址
定义如下:
#include
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地址和端口号。
2.1 服务端示例
#define MAXLINE 4096
#define PORT 6563
#define LISTENQ 1024
#define BUFFER_SIZE 4096
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main() {
int n;
char buff[BUFFER_SIZE];
int listenfd, connfd;
struct sockaddr_in servaddr;//服务器绑定的地址
struct sockaddr_in listendAddr, connectedAddr, peerAddr;//分别表示监听的地址,连接的本地地址,连接的对端地址
int listendAddrLen, connectedAddrLen, peerLen;
char ipAddr[INET_ADDRSTRLEN];//保存点分十进制的地址
if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1 ){//服务器端绑定地址
printf("bind socket error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
if( listen(listenfd, LISTENQ) == -1){
printf("listen socket error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
listendAddrLen = sizeof(listendAddr);
//获取监听的地址和端口
if(getsockname(listenfd, (struct sockaddr *)&listendAddr, &listendAddrLen) == -1){
printf("getsockname error\n");
exit(0);
}
printf("listen address = %s:%d\n", inet_ntoa(listendAddr.sin_addr), ntohs(listendAddr.sin_port));
printf("======waiting for client's request======\n");
while(1) {
if( (connfd = accept(listenfd, (struct sockaddr *)NULL, NULL)) == -1 ){
printf("accept socket error: %s(errno: %d)", strerror(errno), errno);
continue;
}
//获取connfd表示的连接上的本地地址
connectedAddrLen = sizeof(connectedAddr);
if(getsockname(connfd, (struct sockaddr *)&connectedAddr, &connectedAddrLen) == -1){
printf("getsockname error\n");
exit(0);
}
printf("connected server address = %s:%d\n", inet_ntoa(connectedAddr.sin_addr), ntohs(connectedAddr.sin_port));
//获取connfd表示的连接上的对端地址
peerLen = sizeof(peerAddr);
if(getpeername(connfd, (struct sockaddr *)&peerAddr, &peerLen) == -1){
printf("getpeername error\n");
exit(0);
}
printf("connected peer address = %s:%d\n", inet_ntop(AF_INET, &peerAddr.sin_addr, ipAddr, sizeof(ipAddr)), ntohs(peerAddr.sin_port));
n = recv(connfd, buff, MAXLINE, 0);
buff[n] = '\0';
printf("recv msg from client: %s\n", buff);
close(connfd);
}
close(listenfd);
return 0;
}
2.2 客户端示例
#define PORT 6563
#define SEND_SIZE 4096
#include
#include
#include
#include
#include
#include
#include
#include
#include
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地址
char sendline[SEND_SIZE];
if(argc < 2) {
printf("parameter error");
exit(0);
}
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){
printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);
exit(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. addr: %s\n", argv[1]);//地址参数不合法
exit(0);
}
//向服务器端发起连接请求
if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) {
printf("connnect error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
//获取sockfd表示的连接上的本地地址
if(getsockname(sockfd, (struct sockaddr*)&clientAddr, &clientAddrLen) == -1 ){
printf("getsockname error: %s(errno: %d))\n", strerror(errno), errno);
exit(0);
}
printf("client:client ddress = %s:%d\n", inet_ntop(AF_INET, &clientAddr.sin_addr, ipAddress, sizeof(ipAddress)), ntohs(clientAddr.sin_port));
printf("send msg to server: \n");
fgets(sendline, 4096, stdin);
if(send(sockfd, sendline, strlen(sendline), 0) < 0){
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
close(sockfd);
return 0;
}
本文主要参考:https://blog.csdn.net/workformywork/article/details/24554813