通過網絡socket獲取對方 ip 和port


int getpeername(int s, struct sockaddr *name, socklen_t *namelen);
描述
獲取socket的對方地址
struct sockaddr_in sa;
int len = sizeof(sa);
if(!getpeername(sockfd, (struct sockaddr *)&sa, &len))
{
printf( "對方IP:%s ", inet_ntoa(sa.sin_addr));
printf( "對方PORT:%d ", ntohs(sa.sin_port));
}
補充:getsockname和getpeername調度時機很重要,如果調用時機不對,則無法正確獲得地址和端口。
TCP
對於服務器來說,在bind以后就可以調用getsockname來獲取本地地址和端口,雖然這沒有什么太多的意義。getpeername只有在鏈接建立以后才調用,否則不能正確獲得對方地址和端口,所以他的參數描述字一般是鏈接描述字而非監聽套接口描述字。
對於客戶端來說,在調用socket時候內核還不會分配IP和端口,此時調用getsockname不會獲得正確的端口和地址(當然鏈接沒建立更不可能調用getpeername),當然如果調用了bind 以后可以使用getsockname。想要正確的到對方地址(一般客戶端不需要這個功能),則必須在鏈接建立以后,同樣鏈接建立以后,此時客戶端地址和端口就已經被指定,此時是調用getpeername的時機。
UDP
UDP分為鏈接和沒有鏈接2種(這個到UDP與connect可以找到相關內容)
沒有鏈接的UDP不能調用getpeername,但是可以調用getsockname,和TCP一樣,他的地址和端口不是在調用socket就指定了,而是在第一次調用sendto函數以后
已經鏈接的UDP,在調用connect以后,這2個函數都是可以用的(同樣,getpeername也沒太大意義。如果你不知道對方的地址和端口,不可能會調用connect)。

    //獲取fd對應的ip和port
    static void get_peer_ip_port(int fd, char **ip, int *port)
    {
        int client_fd = fd;
        
        // discovery client information
        struct sockaddr_in addr;
        socklen_t addrlen = sizeof(addr);
        if(getpeername(client_fd, (struct sockaddr*)&addr, &addrlen) == -1){
            fprintf(stderr,"discovery client information failed, fd=%d, errno=%d(%#x).\n", client_fd, errno, errno);        
            return;
        }
     
        // ip v4 or v6
        char *buf = malloc(INET6_ADDRSTRLEN);
        memset(buf, 0, INET6_ADDRSTRLEN);
        
        if((inet_ntop(addr.sin_family, &addr.sin_addr, buf, INET6_ADDRSTRLEN)) == NULL){
        fprintf(stderr,"convert client information failed, fd=%d, errno=%d(%#x).\n", client_fd, errno, errno);        
            return;
        }
        *port = ntohs(addr.sin_port);
        fprintf(stdout, "get peer ip of client ip=%s, port=%d, fd=%d\n", buf, *port, client_fd);
        *ip = buf;
        
        return;
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM