getpeername、getsockname

函數原型:服務器

#include<sys/socket.h> 
int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen); 
int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);

函數功能:網絡

getsockname函數用於獲取與某個套接字關聯的本地協議地址
getpeername函數用於獲取與某個套接字關聯的外地協議地址 socket

 

返回值:函數

對於這兩個函數,若是函數調用成功,則返回0,若是調用出錯,則返回-1。spa

 

實例:指針

/***
client.c
***/
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>

#define PORT 6563

int main(int argc, char **argv)
{
    struct sockaddr_in servaddr;
    struct sockaddr_in clientaddr;
    int sockfd;
    int clientaddrlen = sizeof(clientaddr);
    char ipAddress[INET_ADDRSTRLEN];

    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);
    printf("client:clinet address = %s:%d\n",inet_ntop(AF_INET,
                &clientaddr.sin_addr, ipAddress, sizeof(ipAddress)),
            ntohs(clientaddr.sin_port));
    return 0;
}

 

/***
server.c
***/
#include<sys/socket.h>
#include<stdio.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>

#define MAXLINE 4096
#define PORT 6563
#define LISTENQ 1024

int main()
{
    int listenfd, connfd;
    struct sockaddr_in servaddr;
    struct sockaddr_in listenAddr, connecteAddr, peerAddr;
    int listenAddrlen, connectedAddrlen, perrLen;

    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);
    listenAddrlen = sizeof(listenAddr);
    getsockname(listenfd,(struct sockaddr *)&listenAddr, 
            &listenAddrlen);
    printf("listen address = %s:%d\n",inet_ntoa(listenAddr.sin_addr),
            ntohs(listenAddr.sin_port));

    while(1)
    {
        connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
        connectedAddrlen = sizeof(connecteAddr);
        getsockname(connfd, (struct sockaddr*)&connecteAddr, &connectedAddrlen);
        printf("connected server address = %s:%d\n",inet_ntoa(connecteAddr.sin_addr),
                ntohs(connecteAddr.sin_port));

        getpeername(connfd, (struct sockaddr*)&peerAddr, &perrLen);
        printf("connected peer address = %s:%d\n",inet_ntop(AF_INET,
                &peerAddr.sin_addr, ipAddr, sizeof(ipAddr)),
                ntohs(peerAddr.sin_port));
    }

    return 0;
}    

 

運行結果:code

 

 

從上面的代碼中能夠看到,服務器端listenfd套接字描述符對應的地址即爲綁定的通配IP地址和指定的端口,而connfd套接字描述符對應的鏈接的服務器端的地址爲內核賦予的地址和用戶指定的端口。server

 

上面的客戶端與服務器端的代碼中使用了函數inet_ntoa,inet_pton對32位的地址進行轉換,其中inet_ntoa是較老的函數,與它一塊兒的還有函數inet_addr和inet_ntoa,這三個函數的定義以下:blog

#include<arpa/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地址。ip

 

inet_ntoa函數將32位的網絡字節序的IPv4地址轉換成點分十進制的字符串表示的IP地址,inet_addr函數已被廢棄,而且這三個函數只針對IPv4地址有效,在點分十進制數串和32位的網絡字節序二進制值間進行轉換,若是要對於IPv4和IPv6都適用,那麼使用下面兩個函數:

#include<arpa/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地址。

相關文章
相關標籤/搜索