zoukankan      html  css  js  c++  java
  • 获取主机信息,网络信息AIP,getsockname,getpeername,getservbyname,getservbyport,inet_ntop,inet_pton

    获取主机信息

    1.ip地址转换,主机字节序 <---> 网络字节序

    #include <arpa/inet.h>
    
    int inet_pton(int af, const char* src, void* dst);
    
    const char* inet_ntop(int af, const void* src, char* dst, socklen_t cnt)

    inet_pton函数将用字符串表示的IP地址src(用淀粉十进制字符串表示的IPv4地址或用十六进制字符串表示的IPv6地址)转换成用网络字节序整数表示的IP地址,并把转换结果存储于dst指向的内存中。

    其中,af 参数指定地址族,可以使AF_INET或者AF_INET6.inet_pton成功时返回1,失败时返回0,病设置errno。

    inet_ntop函数进行相反的转换,前3个参数含义与inet_pton的参数相同,最后一个参数cnt指定目标存储单元的大小。成功时返回目标存储单元的地址,失败则返回NULL并设置errno。

    这个头文件里面定义了“目标存储单元的大小

    #include <netinet/in.h>
    #define  INET_ADDRESSLEN    16
    #define  INET6_ADDRESSLEN  46

    2.地址信息函数:

    #include <sys/socket.h>
    int getsockname(int sockfd, struct sockaddr* address, socklen_t* address_len);
    int getpeername(int sockfd, struct slckaddr* address, socklen_t* address_len);

         getsockanme获取sockfd对应的本端socket地址,并将其存储于address参数指定的内存中,该socket地址的长度则存储于address_len参数指向的变量中。如果实际socket地址的长度大于address所指内存区的大小,那么该socket地址将被截断。getsocketname成功时返回0,失败则返回-1,并设置errno。

        getpeername获取sockfd对应的远端socket地址,其参数及返回值的含义与getsockname的参数及返回值相同。

    3.网络信息AIP

    #include <netdb.h>
    struct hostent* gethostbyname(const char* name);
    struct hostent* gethostbyaddr(const void* addr, size_t len, int type);
    
    struct hostent
    {
        char* h_name;
        char** h_aliases;
        int h_addrtype;
        int h_length;
        char** h_addr_list;//按网络字节序列出的主机IP地址列表
    };

    gethostbyname 函数根据主机名称获取主机的完整信息,
    gethostbyaddr函数根据IP地址获取主机的完整信息。
    gethostbyname函数通常先在本地的 /etc/hsots配置的文件中查找主机,
    如果没有找到,再去访问DNS服务器。

    #include <netdb.h>
    struct servent* getservbyname(const char* name, const char* proto);
    struct servent* getsrvbyport(int port, const char* proto);
    
    struct servent
    {
        char* s_name;
        char** s_aliases;
        int s_port;
        char* s_proto;
    };

    getservbyname函数根据名称获取某个服务的完整信息,
    getsrvbyport函数根据端口号获取某个服务的完整信息。
    他们实际上都是通过读取 /etc/services 文件来获取服务信息的

    #include <netdb.h>
    int getaddrinfo(const char* hostname, const char* service, const struct addrinfo* hints, struct addrinfo** result)
    
    struct addrinfo
    {
        int ai_flags;
        int ai_family;
        int ai_socktype;
        int ai_protocol;
        socklent_t ai_addrlen;
        char* ai_canonname;
        struct sockaddr* ai_addr;
        struct addrinfo* ai_next;
    };

    getaddrinfo函数既能通过主机名获取ip地址也能通过服务名获得端口号。

    #include <netdb.h>
    int getnameinfo(const struct sockaddr* sockaddr, socklen_t addrlen, char* host, socklen_t hostlen, char* serv, socklen_t servlen, int flags);

    getnameinfo函数能通过socket地址同时获得以字符串表示的主机名和服务名。

    4.举例说明:

    举个例子A:

        const char* ip = argv[1];
        int port = atoi(argv[2]);
        int backlog = atoi(argv[3]);
    
        int sock = socket(PF_INET, SOCK_STREAM, 0);
        assert(socket >= 0);
    
        // create a ipv4 socket address
        struct sockaddr_in address;
        bzero(&address, sizeof(address));
        address.sin_family = AF_INET;
        inet_pton(AF_INET, ip, &address.sin_addr);
        address.sin_port = htons(port);

    举个例子B:

    if(connect(sock, (struct sockaddr*)&serverSocket, sizeof(serverSocket)) != -1)
        {
            char buffer[BUFFER_SIZE];
            memset(buffer, '', sizeof(buffer));
            send(sock, buffer, BUFFER_SIZE, 0);
                            
            //client get server(peer) name
            struct sockaddr_in peerHost;
            socklen_t client_addrlength = sizeof(peerHost);
            getpeername(sock, (struct sockaddr*)&peerHost, &client_addrlength );
            char dest[100] ;
            inet_ntop(AF_INET, &peerHost.sin_addr,dest,100);
            int peerPort=ntohs(peerHost.sin_port);
            printf("dest ip : %s, port:%d", dest, peerPort);
        }

    举个例子C:(完整版. 客户端)

    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define BUFFER_SIZE  512
    
    int main(int argc, char* argv[])
    {
        if(argc<=2)
        {
            printf("usage: %s ip_address, port_number send_buffer_size 
    ", basename(argv[0]));
            return 1;
        }
        
        char* ip = argv[1];
        int port = atoi(argv[2]);
    
        struct sockaddr_in serverSocket;
        bzero(&serverSocket, sizeof(serverSocket));
    
        serverSocket.sin_port = htons(port);
        serverSocket.sin_family = AF_INET;
        inet_pton(AF_INET, ip , &serverSocket.sin_addr);
        
        int sock = socket(PF_INET, SOCK_STREAM, 0);
        assert(sock>=0);
        
        int sendBuf =atoi(argv[3]);
        int len = sizeof(sendBuf);
        //set tcp buff ,and read
        setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendBuf, sizeof(sendBuf));
        getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendBuf, (socklen_t*)&len);
        printf("the tcp send buffer size after setting is %d.
    ", sendBuf);
        
        if(connect(sock, (struct sockaddr*)&serverSocket, sizeof(serverSocket)) != -1)
        {
            char buffer[BUFFER_SIZE];
            memset(buffer, '', sizeof(buffer));
            send(sock, buffer, BUFFER_SIZE, 0);
            
            
            
            //client get server(peer) name
            struct sockaddr_in peerHost;
            socklen_t client_addrlength = sizeof(peerHost);
            getpeername(sock, (struct sockaddr*)&peerHost, &client_addrlength );
            char dest[100] ;
            inet_ntop(AF_INET, &peerHost.sin_addr,dest,100);
            int peerPort=ntohs(peerHost.sin_port);
            printf("dest ip : %s, port:%d", dest, peerPort);
        }
        
        close(sock);    
    
        return 0;
    }

    举个例子D:完整版(服务器)

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    
    #define BUFFER_SIZE 1024
    
    int main(int argc, char* argv[])
    {
        if(argc<=2)
        {
            printf("suage:%s IP_number port_number recv_buffer.
    ", basename(argv[0]));
            return 1;
        }
    
        char* ip = argv[1];
        int port = atoi(argv[2]);
        
        struct sockaddr_in serverAddr;
        bzero(&serverAddr,sizeof(serverAddr));
        
        serverAddr.sin_family = AF_INET;
        serverAddr.sin_port = htons(port);
        inet_pton(AF_INET,ip, &serverAddr.sin_addr);
        
        int sockfd = socket(PF_INET, SOCK_STREAM,0);
        assert(sockfd>=0);
        
        int recvbuf = atoi(argv[3]);
        int len = sizeof(recvbuf);
        //set tcp bufsize,then read it.
        setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof(recvbuf));
        getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &recvbuf, (socklen_t*)&len);
        printf("The tcp receive buffer size after setting is %d.
    ", recvbuf);
    
        int ret = bind(sockfd, (struct sockaddr*)&serverAddr,sizeof(serverAddr));
        assert(ret>=0);
        
        ret = listen(sockfd, 5);
        assert(ret>=0);
    
        struct sockaddr_in client;
        socklen_t client_addrlength = sizeof(client);
        int connfd = accept(sockfd, (struct sockaddr*)&client, &client_addrlength);
        if(connfd < 0)
        {
            printf("errno is:%d 
    ", errno);
        }
        else
        {
            char buffer[BUFFER_SIZE];
            memset(buffer,'', sizeof(buffer));
            while(recv(connfd, buffer, BUFFER_SIZE-1, 0) > 0)
            {
               printf("recv success...");
            }
            
            close(connfd);
        }    
        
        close(sockfd);
    
        return 0;
    }

    举个例子E:完整版(访问某个开启了daytime的主机)

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <assert.h>
    
    int main(int argc, char* argv[])
    {
        assert(argc ==2);
        char* host = argv[1];
        //get dest host ip info
        struct hostent* hostinfo = gethostbyname(host);
        assert(hostinfo);
        
        //get daytime info
        struct servent* servinfo = getservbyname("daytime", "tcp");
        assert(servinfo);
    
    //// attention the struct convert
        struct in_addr pNetIp = *(struct in_addr*)*hostinfo->h_addr_list;  
        char serverHostIp[100] ;
        inet_ntop(AF_INET, &pNetIp, serverHostIp, 100);
            
        printf("server host ip:[%s].daytime port is %d.
    ",serverHostIp, ntohs(servinfo->s_port));
        
        struct sockaddr_in address;
        bzero(&address, sizeof(address));
        address.sin_family = AF_INET;
        address.sin_port = servinfo->s_port;
        
        // Attention! directly use servent 
        address.sin_addr = *(struct in_addr*)*hostinfo->h_addr_list;
        
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        int result = connect(sockfd, (struct sockaddr*)&address, sizeof(address));
        assert(result != -1);
        
        char buffer[128];
        result = read(sockfd, buffer, sizeof(buffer));
        assert(result > 0);
        buffer[result] = '';
        printf("the day time is: %s", buffer);
    
        close(sockfd);
        return 0;
    }
  • 相关阅读:
    基础总结篇之一:Activity生命周期
    putExtra方法
    fork函数
    linux中fork()函数详解(原创!!实例讲解) (转载)
    系统调用wait、waitpid和exec函数
    版本控制工具VSS使用介绍
    学习进度条六(第七周)
    阶段冲刺4
    阶段冲刺3
    阶段冲刺2
  • 原文地址:https://www.cnblogs.com/music-liang/p/11911285.html
Copyright © 2011-2022 走看看