socket编程之获取客户端和服务端ip

1. getsockname和getpeername函数

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. 示例程序

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

你可能感兴趣的:(network)