wangzhengquan
2020-10-13 d6a27f15acd08e99841595cece2b3e3e8045491a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* is_seqnum_sv.c
 
   A simple Internet stream socket server. Our service is to provide
   unique sequence numbers to clients.
 
   Usage:  is_seqnum_sv [init-seq-num]
                        (default = 0)
 
   See also is_seqnum_cl.c.
*/
#define _BSD_SOURCE             /* To get definitions of NI_MAXHOST and
                                   NI_MAXSERV from <netdb.h> */
#include <netdb.h>
#include "is_seqnum.h"
 
#define BACKLOG 50
 
int
main(int argc, char *argv[])
{
    char line[1024];            /* Length of requested sequence */
    struct sockaddr_storage claddr;
    int lfd, cfd, optval;
    socklen_t addrlen;
    struct addrinfo hints;
    struct addrinfo *result, *rp;
#define ADDRSTRLEN (NI_MAXHOST + NI_MAXSERV + 10)
    char addrStr[ADDRSTRLEN];
    char host[NI_MAXHOST];
    char service[NI_MAXSERV];
 
    if (argc > 1 && strcmp(argv[1], "--help") == 0)
        printf("%s [init-seq-num]\n", argv[0]);
 
 
    /* Ignore the SIGPIPE signal, so that we find out about broken connection
       errors via a failure from write(). */
 
    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)    err_exit(errno, "signal");
 
    /* Call getaddrinfo() to obtain a list of addresses that
       we can try binding to */
 
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_canonname = NULL;
    hints.ai_addr = NULL;
    hints.ai_next = NULL;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_family = AF_UNSPEC;        /* Allows IPv4 or IPv6 */
    hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
                        /* Wildcard IP address; service name is numeric */
 
    if (getaddrinfo(NULL, PORT_NUM, &hints, &result) != 0)
        err_exit(errno, "getaddrinfo");
 
    /* Walk through returned list until we find an address structure
       that can be used to successfully create and bind a socket */
 
    optval = 1;
    for (rp = result; rp != NULL; rp = rp->ai_next) {
        lfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if (lfd == -1)
            continue;                   /* On error, try next address */
 
        if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1)
             err_exit(errno, "setsockopt");
 
        if (bind(lfd, rp->ai_addr, rp->ai_addrlen) == 0)
            break;                      /* Success */
 
        /* bind() failed: close this socket and try next address */
        close(lfd);
    }
 
    if (rp == NULL)
        err_exit(errno, "Could not bind socket to any address");
 
    if (listen(lfd, BACKLOG) == -1)
        err_exit(errno, "listen");
 
    freeaddrinfo(result);
 
    for (;;) {                  /* Handle clients iteratively */
 
        /* Accept a client connection, obtaining client's address */
 
        addrlen = sizeof(struct sockaddr_storage);
        cfd = accept(lfd, (struct sockaddr *) &claddr, &addrlen);
        if (cfd == -1) {
            err_msg(errno, "accept");
            continue;
        }
 
        if (getnameinfo((struct sockaddr *) &claddr, addrlen,
                    host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
            snprintf(addrStr, ADDRSTRLEN, "(%s, %s)", host, service);
        else
            snprintf(addrStr, ADDRSTRLEN, "(?UNKNOWN?)");
        printf("Connection from %s\n", addrStr);
 
        /* Read client request, send sequence number back */
 
        if (readLine(cfd, line, 1024) <= 0) {
            close(cfd);
            continue;                   /* Failed read; skip request */
        }
 
        if (write(cfd, line, strlen(line)) != strlen(line))
            fprintf(stderr, "Error on write");
 
        if (close(cfd) == -1)           
            err_msg(errno, "close");
    }
}