UNP函数笔记八: 名字与地址转换

58 篇文章 0 订阅
49 篇文章 0 订阅

第十一章  名字与地址转换:

#include <netdb.h>
struct hostnet * gethostbyname(const char * hostname);
    error return NULL and set h_errno
    struct hostnet {
        char  * h_name;       /* official (canonical) name of host */
        char ** h_aliases;    /* alias name */
        int     h_addrtype;   /* host addr type: AF_INET */
        int     h_length;     /* length of address: 4 */
        char ** h_addr_list;  /* IPv4 addrs */
    };
    h_errno:
        HOST_NOT_FOUND, TRY_AGAIN, NO_RECOVERY, NO_DATA(NO_ADDRESS)

#include <netdb.h>
struct hostnet * gethostbyaddr(const char * addr, socklen_t len, int family);
    error return NULL and set h_errno
    addr:
        real type is struct in_addr
    family:
        AF_INET
    len:
        4, sizeof(struct in_addr)

#include <netdb.h>
struct servent * getservbyname(const char * servname, const char * protoname);
    error return NULL
    struct servent {
        char  * s_name;    /* official service name */
        char ** s_aliases; /* alias list */
        int     s_port;    /* network byte order */
        char  * s_proto;   /* protocol to use */
    };
    protoname:
        "tcp", "udp", NULL

#include <netdb.h>
struct servent * getservbyport(int port, const_char * protoname);
    error return NULL
    port:
        network byte order
    protoname:
        "tcp", "udp", NULL

#include <netdb.h>
int getaddrinfo(const char * hostname, const char * service, 
                const struct addrinfo * hints, struct addrinfo ** result);
    success return 0, failed return error(EAI_xxx)
    error:
        EAI_AGAIN,  EAI_BADFLAGS, EAI_FAIL,    EAI_FAMILY,   EAI_MEMORY, 
        EAI_NONAME, EAI_OVERFLOW, EAI_SERVICE, EAI_SOCKTYPE, EAI_SYSTEM
    struct addrinfo {
        int         ai_flags;
        int         ai_family;
        int         ai_socktype;
        int         ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
        socklen_t   ai_addrlen;  /* length of ai_addr */
        char      * ai_canonname;
        struct sockaddr * ai_addr;
        struct addrinfo * ai_next;
    };
    hints only can set: ai_flags, ai_family, ai_socktype, ai_protocol
    ai_flags:
        AI_PASSIVE,  AI_CANONNAME, AI_NUMERICHOST, AI_NUMERICSERV, 
        AI_V4MAPPED, AI_ALL,       AI_ADDRCONFIG

#include <netdb.h>
const char * gai_strerror(int error);

#include <netdb.h>
void freeaddrinfo(struct addrinfo * ai);

some hostname:
    0::0, 0.0.0.0; 0::1, 127.0.0.1

#include <netdb.h>
int getnameinfo(const struct sockaddr * sockaddr, socklen_t addrlen, 
                char * host, socklen_t hostlen, 
                char * serv, socklen_t servlen, int flags);
    success return 0, failed return error(EAI_xxx)
    flags:
        NI_DGRAM,       NI_NAMEREQD,     NI_NOFQDN, 
        NI_NUMERICHOST, NI_NUMERICSCOPE, NI_NUMERICSERV

#include <netdb.h>
struct hostent * gethostbyname_r(const char * hostname, 
                                 struct hostnet * result, 
                                 char * buf, int buflen, int * h_errnop);
    error return NULL
    buflen should >= 8192
struct hostent * gethostbyaddr_r(const char * addr, int len, int type, 
                                 struct hostnet * result, 
                                 char * buf, int buflen, int * h_errnop);
    error return NULL
    buflen should >= 8192

other functions:
    getXXXent, setXXXent, endXXXent
        XXX:host, net, proto, serv
    getnetbyaddr, getnetbyname, 
    getprotobyname, getprotobynumber

示例:

#include <netdb.h>

#include "err_exit.h"

int 
main(int argc, char ** argv)
{
    char           *  ptr;
    char           ** pptr;
    char              str[INET_ADDRSTRLEN];
    struct hostent  * hptr;

    while (--argc > 0) {
        ptr = *++argv;
        if ((hptr = gethostbyname(ptr)) == NULL) {
            printf("gethostbyname error for host: %s: %s\n",
                   ptr, hstrerror(h_errno));
            continue;
        }
        printf("official hostname: %s\n", hptr->h_name);

        for (pptr = hptr->h_aliases; *pptr != NULL; ++pptr) {
            printf("\talias: %s\n", *pptr);
        }

        switch (hptr->h_addrtype)
        {
            case AF_INET:
            {
                pptr = hptr->h_addr_list;
                for (; *pptr != NULL; ++pptr) {
                    if (inet_ntop(hptr->h_addrtype, *pptr, 
                                  str, sizeof(str)) == NULL) {
                        err_exit("inet_ntop error");
                    }
                    printf("\taddress: %s\n", str);
                }
                break;
            }
            default:
            {
                err_exit("unknown address type");
                break;
            }
        }
    }
    exit(0);
}

#include <netdb.h>

#include "err_exit.h"
#include "sock_ntop.h"

#define MAXLINE 4096

int 
main(int argc, char ** argv)
{
    int                   sockfd;
    int                   n;
    char                * paddr;
    char                  recvline[MAXLINE + 1];
    struct sockaddr_in    servaddr;
    struct in_addr     ** pptr;
    struct in_addr      * inetaddrp[2];
    struct in_addr        inetaddr;
    struct hostent      * hp;
    struct servent      * sp;

    if (argc != 3) {
        printf("usage: daytimetcpcli1 <hostname> <service>\n");
        exit(1);
    }

    if ((hp = gethostbyname(argv[1])) == NULL) {
        if (inet_aton(argv[1], &inetaddr) <= 0) {
            printf("hostname error for %s: %s\n", argv[1], hstrerror(h_errno));
            exit(1);
        }
        else {
            inetaddrp[0] = &inetaddr;
            inetaddrp[1] = NULL;
            pptr = inetaddrp;
        }
    }
    else {
        pptr = (struct in_addr **)hp->h_addr_list;
    }

    if ((sp = getservbyname(argv[2], "tcp")) == NULL) {
        printf("gethostbyname error for host: %s: %s\n",
               argv[2], hstrerror(h_errno));
        exit(1);
    }

    for (; *pptr != NULL; ++pptr) {
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
            err_exit("socket error");
        }

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = sp->s_port;
        memcpy(&servaddr.sin_addr, *pptr, sizeof(struct in_addr));

        if ((paddr = sock_ntop((struct sockaddr *)&servaddr, 
                               sizeof(servaddr))) == NULL) {
            err_exit("sock_ntop error");
        }
        printf("trying %s\n", paddr);

        if (connect(sockfd, (struct sockaddr *)&servaddr, 
                    sizeof(servaddr)) == 0) {
            break;  /* success */
        }
        printf("connect error: %s\n", strerror(errno));
        if (close(sockfd) == -1) {
            err_exit("close error");
        }
    }
    if (*pptr == NULL) {
        printf("unable to connect");
        exit(1);
    }

    while ((n = read(sockfd, recvline, MAXLINE)) > 0) {
        recvline[n] = '\0';  /* null terminate */
        if (fputs(recvline, stdout) == EOF) {
            err_exit("fputs error");
        }
    }
    if (n < 0) {
        err_exit("read error");
    }

    exit(0);
}

#include <stdio.h>
#include <netdb.h>
#include <strings.h>

struct addrinfo * 
host_serv(const char * host, const char * serv, int family, int socktype)
{
    int               n;
    struct addrinfo   hints;
    struct addrinfo * res;

    bzero(&hints, sizeof(struct addrinfo));
    hints.ai_flags = AI_CANONNAME;  /* always return canonical name */
    hints.ai_family = family;       /* AF_UNSPEC, AF_INET, AF_INET6, etc. */
    hints.ai_socktype = socktype;   /* 0, SOCK_STREAM, SOCK_DGRAM, etc. */

    if ((n = getaddrinfo(host, serv, &hints, &res)) != 0) {
        printf("host_serv error for %s, %s: %s\n", 
               (host == NULL) ? "(no hostname)" : host, 
               (serv == NULL) ? "(no servname)" : serv, 
               gai_strerror(n));
        exit(1);
    }

    return(res);  /* return pointer to first on linked list */
}

#include <netdb.h>
#include <strings.h>

#include "err_exit.h"

#define LISTENQ 1024

int 
tcp_listen(const char * host, const char * serv, socklen_t * addrlenp)
{
    int               listenfd;
    int               n;
    const int         on = 1;
    struct addrinfo   hints; 
    struct addrinfo * res;
    struct addrinfo * ressave;

    bzero(&hints, sizeof(struct addrinfo));
    hints.ai_flags = AI_PASSIVE;
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    if ((n = getaddrinfo(host, serv, &hints, &res)) != 0) {
        printf("host_serv error for %s, %s: %s\n", 
               (host == NULL) ? "(no hostname)" : host, 
               (serv == NULL) ? "(no servname)" : serv, 
               gai_strerror(n));
        exit(1);
    }
    ressave = res;

    do {
        listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
        if (listenfd == -1) {
            continue;  /* error, try next one */
        }

        if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, 
                       &on, sizeof(on)) == -1) {
            err_exit("setsockopt error");
        }

        if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0) {
            break;  /* success */
        }

        /* bind error, close and try next one */
        if (close(listenfd) == -1) {
            err_exit("close error");
        }
    } while ((res = res->ai_next) != NULL);

    if (res == NULL) {  /* errno from final socket() or bind() */
        printf("tcp_listen error for %s, %s\n", host, serv);
        exit(1);
    }

    if (listen(listenfd, LISTENQ) == -1) {
        err_exit("listen error");
    }

    if (addrlenp != NULL) {
        *addrlenp = res->ai_addrlen;  /* return size of protocol address */
    }

    freeaddrinfo(ressave);

    return(listenfd);
}

#include <netdb.h>
#include <strings.h>

#include "err_exit.h"

int 
tcp_connect(const char * host, const char * serv)
{
    int               sockfd;
    int               n;
    struct addrinfo   hints; 
    struct addrinfo * res;
    struct addrinfo * ressave;

    bzero(&hints, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    if ((n = getaddrinfo(host, serv, &hints, &res)) != 0) {
        printf("host_serv error for %s, %s: %s\n", 
               (host == NULL) ? "(no hostname)" : host, 
               (serv == NULL) ? "(no servname)" : serv, 
               gai_strerror(n));
        exit(1);
    }
    ressave = res;

    do {
        sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
        if (sockfd == -1) {
            continue;  /* ignore this one */
        }

        if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0) {
            break;  /* success */
        }

        if (close(sockfd) == -1) {
            err_exit("close error");
        }
    } while ((res = res->ai_next) != NULL);

    freeaddrinfo(ressave);

    if (res == NULL) {  /* errno set from final connect() */
        printf("tcp_connect error for %s, %s\n", host, serv);
        exit(1);
    }

    return(sockfd);
}

#include <time.h>
#include <netdb.h>

#include "err_exit.h"
#include "sock_ntop.h"
#include "tcp_listen.h"

#define MAXLINE 4096

int 
main(int argc, char ** argv)
{
    int                      n;
    int                      listenfd;
    int                      connfd;
    socklen_t                len;
    socklen_t                addrlen;
    char                     buff[MAXLINE];
    time_t                   ticks;
    struct sockaddr_storage  cliaddr;

    if (argc == 2) {
        listenfd = tcp_listen(NULL, argv[1], &addrlen);
    }
    else if (argc == 3) {
        listenfd = tcp_listen(argv[1], argv[2], &addrlen);
    }
    else {
        printf("usage: daytimetcpsrv2 [ <host> ] <service or port>\n");
        exit(1);
    }

    for ( ; ; ) {
        len = sizeof(cliaddr);
        if ((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, 
                            &len)) == -1) {
            err_exit("accept error");
        }
        printf("connection from %s\n", 
               sock_ntop((struct sockaddr *)&cliaddr, len));

        ticks = time(NULL);
        snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
        n = strlen(buff);
        if (write(connfd, buff, n) != n) {
            err_exit("write error");
        }

        if (close(connfd) == -1) {
            err_exit("close error");
        }
    }
}

#include <netdb.h>

#include "err_exit.h"
#include "sock_ntop.h"
#include "tcp_connect.h"

#define MAXLINE 4096

int 
main(int argc, char ** argv)
{
    int                       sockfd;
    int                       n;
    char                    * paddr;
    char                      recvline[MAXLINE + 1];
    socklen_t                 len;
    struct sockaddr_storage   ss;

    if (argc != 3) {
        printf("usage: daytimetcpcli <hostname/IPaddress> <service/port#>\n");
        exit(1);
    }

    sockfd = tcp_connect(argv[1], argv[2]);

    len = sizeof(ss);
    if (getpeername(sockfd, (struct sockaddr *)&ss, &len) == -1) {
        err_exit("getpeername error");
    }

    if ((paddr = sock_ntop((struct sockaddr *)&ss, len)) == NULL) {
        err_exit("sock_ntop error");
    }
    printf("connected to %s\n", paddr);

    while ((n = read(sockfd, recvline, MAXLINE)) > 0) {
        recvline[n] = '\0';  /* null terminate */
        if (fputs(recvline, stdout) == EOF) {
            err_exit("fputs error");
        }
    }
    if (n < 0) {
        err_exit("read error");
    }

    exit(0);
}

#include <netdb.h>
#include <strings.h>

#include "err_exit.h"

int 
udp_client(const char * host, const char * serv, 
           struct sockaddr ** saptr, socklen_t * lenp)
{
    int               sockfd;
    int               n;
    struct addrinfo   hints; 
    struct addrinfo * res;
    struct addrinfo * ressave;

    bzero(&hints, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;

    if ((n = getaddrinfo(host, serv, &hints, &res)) != 0) {
        printf("host_serv error for %s, %s: %s\n", 
               (host == NULL) ? "(no hostname)" : host, 
               (serv == NULL) ? "(no servname)" : serv, 
               gai_strerror(n));
        exit(1);
    }
    ressave = res;

    do {
        sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
        if (sockfd != -1) {
            break;  /* success */
        }
    } while ((res = res->ai_next) != NULL);

    if (res == NULL) {  /* errno set from final socket() */
        printf("udp_client error for %s, %s\n", host, serv);
    }

    if ((*saptr = (struct sockaddr *)malloc(res->ai_addrlen)) == NULL) {
        err_exit("malloc error");
    }
    memcpy(*saptr, res->ai_addr, res->ai_addrlen);
    if (lenp != NULL) {
        *lenp = res->ai_addrlen;
    }

    freeaddrinfo(ressave);

    return(sockfd);
}

#include <netdb.h>
#include <strings.h>

#include "err_exit.h"

int 
udp_server(const char * host, const char * serv, socklen_t * addrlenp)
{
    int               sockfd;
    int               n;
    struct addrinfo   hints; 
    struct addrinfo * res;
    struct addrinfo * ressave;

    bzero(&hints, sizeof(struct addrinfo));
    hints.ai_flags = AI_PASSIVE;
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;

    if ((n = getaddrinfo(host, serv, &hints, &res)) != 0) {
        printf("host_serv error for %s, %s: %s\n", 
               (host == NULL) ? "(no hostname)" : host, 
               (serv == NULL) ? "(no servname)" : serv, 
               gai_strerror(n));
        exit(1);
    }
    ressave = res;

    do {
        sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
        if (sockfd == -1) {
            continue;  /* error - try next one */
        }

        if (bind(sockfd, res->ai_addr, res->ai_addrlen) == 0) {
            break;  /* success */
        }

        if (close(sockfd) == -1) {  /* bind error - close and try next one */
            err_exit("close error");
        }
    } while ((res = res->ai_next) != NULL);

    if (res == NULL) {  /* errno from final socket() or bind() */
        printf("udp_server error for %s, %s\n", host, serv);
        exit(1);
    }

    if (addrlenp != NULL) {
        *addrlenp = res->ai_addrlen;  /* return size of protocol address */
    }

    freeaddrinfo(ressave);

    return(sockfd);
}

#include <netdb.h>
#include <strings.h>

#include "err_exit.h"

int 
udp_connect(const char * host, const char * serv)
{
    int               sockfd;
    int               n;
    struct addrinfo   hints; 
    struct addrinfo * res;
    struct addrinfo * ressave;

    bzero(&hints, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;

    if ((n = getaddrinfo(host, serv, &hints, &res)) != 0) {
        printf("host_serv error for %s, %s: %s\n", 
               (host == NULL) ? "(no hostname)" : host, 
               (serv == NULL) ? "(no servname)" : serv, 
               gai_strerror(n));
        exit(1);
    }
    ressave = res;

    do {
        sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
        if (sockfd == -1) {
            continue;  /* ignore this one */
        }

        if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0) {
            break;  /* success */
        }

        if (close(sockfd) == -1) {
            err_exit("close error");
        }
    } while ((res = res->ai_next) != NULL);

    if (res == NULL) {  /* errno set from final connect() */
        printf("udp_connect error for %s, %s\n", host, serv);
    }

    freeaddrinfo(ressave);

    return(sockfd);
}

#include <time.h>
#include <netdb.h>

#include "err_exit.h"
#include "sock_ntop.h"
#include "udp_server.h"

#define MAXLINE 4096

int 
main(int argc, char ** argv)
{
    int                       sockfd;
    ssize_t                   n;
    char                    * paddr;
    char                      buff[MAXLINE];
    time_t                    ticks;
    socklen_t                 len;
    struct sockaddr_storage   cliaddr;

    if (argc == 2) {
        sockfd = udp_server(NULL, argv[1], NULL);
    }
    else if (argc == 3) {
        sockfd = udp_server(argv[1], argv[2], NULL);
    }
    else {
        printf("usage: daytimeudpsrv [ <host> ] <service or port>\n");
        exit(1);
    }

    for ( ; ; ) {
        len = sizeof(cliaddr);
        n = recvfrom(sockfd, buff, MAXLINE, 0, 
                     (struct sockaddr *)&cliaddr, &len);
        if ((paddr = sock_ntop((struct sockaddr *)&cliaddr, len)) == NULL) {
            printf("sock_ntop error");
        }
        printf("datagram from %s\n", paddr);

        ticks = time(NULL);
        snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
        n = strlen(buff);
        if (sendto(sockfd, buff, n, 0, (struct sockaddr *)&cliaddr, len) != n) {
            err_exit("sendto error");
        }
    }
}

#include <netdb.h>

#include "err_exit.h"
#include "sock_ntop.h"
#include "udp_client.h"

#define MAXLINE 4096

int 
main(int argc, char ** argv)
{
    int               sockfd;
    int               n;
    char            * paddr;
    char              recvline[MAXLINE + 1];
    socklen_t         salen;
    struct sockaddr * sa;

    if (argc != 3) {
        printf("usage: daytimeudpcli1 <hostname/IPaddress> <service/port#>\n");
        exit(1);
    }

    sockfd = udp_client(argv[1], argv[2], &sa, &salen);

    if ((paddr = sock_ntop(sa, salen)) == NULL) {
        err_exit("sock_ntop error");
    }
    printf("sending to %s\n", paddr);

    if (sendto(sockfd, "", 1, 0, sa, salen) != 1) {  /* send 1-byte datagram */
        err_exit("sendto error");
    }

    if (n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL) < 0) {
        err_exit("recvfrom error");
    }
    recvline[n] = '\0';  /* null terminate */
    if (fputs(recvline, stdout) == EOF) {
        err_exit("fputs error");
    }

    exit(0);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值