zhuang@linux:~/notes/man/poll/$ cat

poll

$ grep tags poll.md

Manual pages for getaddrinfo.

Example

Client Side

c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int main(void)
{
    struct addrinfo hints;
    struct addrinfo *res;
    struct addrinfo *rp;
    int sockfd;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;      // IPv4 或 IPv6
    hints.ai_socktype = SOCK_STREAM;  // TCP

    int ret = getaddrinfo("127.0.0.1", "8888",
                          &hints, &res);
    if (ret != 0)
    {
        fprintf(stderr, "getaddrinfo: %s\n",
                gai_strerror(ret));
        return 1;
    }

    for (rp = res; rp != NULL; rp = rp->ai_next)
    {
        sockfd = socket(rp->ai_family,
                        rp->ai_socktype,
                        rp->ai_protocol);

        if (sockfd == -1)
            continue;

        if (connect(sockfd,
                    rp->ai_addr,
                    rp->ai_addrlen) == 0)
        {
            printf("connected\n");
            break;
        }

        close(sockfd);
    }

    freeaddrinfo(res);

    if (rp == NULL)
    {
        fprintf(stderr, "could not connect\n");
        return 1;
    }

    /* begin to communicate with server */

    close(sockfd);

    return 0;
}

Server Side

c
// todo: set_nonblocking
int network_listen(const char* host, const char* port)
{
    (void)host;
    struct addrinfo hints;
    struct addrinfo *res;
    struct addrinfo *rp;

    int listenfd = -1;
    int ret;

    memset(&hints, 0, sizeof(hints));

    hints.ai_family = AF_UNSPEC;      // IPv4 or IPv6
    hints.ai_socktype = SOCK_STREAM;  // TCP
    hints.ai_flags = AI_PASSIVE;

    ret = getaddrinfo(NULL,
                      port,
                      &hints,
                      &res);

    if (ret != 0)
    {
        fprintf(stderr,
                "getaddrinfo: %s\n",
                gai_strerror(ret));
        return -1;
    }

    for (rp = res; rp != NULL; rp = rp->ai_next)
    {
        listenfd = socket(rp->ai_family,
                          rp->ai_socktype,
                          rp->ai_protocol);

        if (listenfd == -1)
            continue;

        int opt = 1;

        /*
         * SO_REUSEADDR:
         * allow port to use again quickly.
         *
         * case:
         *   when server exit and start,
         *   port maybe still stuck at TIME_WAIT status.
         *   if not open this, will show ``Address already in use''
         */
        setsockopt(listenfd,
                   SOL_SOCKET,
                   SO_REUSEADDR,
                   &opt,
                   sizeof(opt));

        if (bind(listenfd,
                 rp->ai_addr,
                 rp->ai_addrlen) == 0)
        {
            break;
        }

        close(listenfd);
        listenfd = -1;
    }

    freeaddrinfo(res);
    
    if (listenfd == -1)
        return -1;

    if (listen(listenfd, SOMAXCONN) == -1)
    {
        close(listenfd);
        return -1;
    }

    return listenfd;
}

zhuang@linux:~/notes/man/poll/$ comments