APUE Learning Example Source Code
guowenxue
2023-11-06 14bbb45d375b611d19494874996e94aad64cf912
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*********************************************************************************
 *      Copyright:  (C) 2018 LingYun IoT Studio
 *                  All rights reserved.
 *
 *       Filename:  socket_server.c
 *    Description:  This file is TCP socket server example source code.
 *
 *        Version:  1.0.0(10/23/2018)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "2017-10-23 01:41:05 PM"
 *
 ********************************************************************************/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <getopt.h>
 
#define BACKLOG              13
 
void print_usage(char *progname)
{
    printf("%s usage: \n", progname);
    printf("-p(--port): sepcify server listen port.\n");
    printf("-h(--Help): print this help information.\n");
 
    return ;
}
 
int main(int argc, char **argv)
{
    int                     rv = -1;
    int                     listen_fd,  client_fd = -1;
    struct sockaddr_in      serv_addr;
    struct sockaddr_in      cli_addr;
    int                     port = 8889;
    socklen_t               addr_len = sizeof(cli_addr);
    char                    buf[1024];
    int                     reuse = 1;
 
    int                     ch;
    struct option           opts[] = {
        {"port", required_argument, NULL, 'p'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };
 
    while( (ch=getopt_long(argc, argv, "p:h", opts, NULL)) != -1 )
    {
        switch(ch)
        {
            case 'p':
                port=atoi(optarg);
                break;
 
            case 'h':
                print_usage(argv[0]);
                return 0;
        }
 
    }
 
    if( !port )
    {
        print_usage(argv[0]);
        return 0;
    }
 
 
 
    /* create TCP socket */
    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(listen_fd < 0 )
    {
        printf("create socket failure: %s\n", strerror(errno));
        return -1;
    }
    printf("socket create fd[%d]\n", listen_fd);
 
    /* Fix port can not be used when stop server program and run it again immediately. */
    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
 
    /* bind socket server information */
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if( bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0 )
    {
        printf("create socket failure: %s\n", strerror(errno));
        return -2;
    }
    printf("socket[%d] bind on port[%d] for all IP address ok\n", listen_fd, port);
 
    /* start listen socket */
    listen(listen_fd, BACKLOG);
 
    while(1)
    {
        /* accept new incoming socket client  */
        printf("\nStart waiting and accept new client connect...\n");
        client_fd = accept(listen_fd, (struct sockaddr*)&cli_addr, &addr_len);
        if(client_fd < 0)
        {
            printf("accept new socket failure: %s\n", strerror(errno));
            return -2;
        }
        printf("Accept new client[%s:%d] with fd [%d]\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), client_fd);
 
        while(1)
        {
            /* receive message from socket client */
            memset(buf, 0, sizeof(buf));
            if( (rv=read(client_fd, buf, sizeof(buf))) < 0)
            {
                printf("Read data from client socket[%d] failure: %s\n", client_fd, strerror(errno));
                close(client_fd);
                break;
            }
            else if( rv == 0 )
            {
                printf("client socket[%d] disconnected\n", client_fd);
                close(client_fd);
                break;
            }
 
            printf("Read [%d] bytes data from socket client[%d]: %s\n", rv, client_fd, buf);
 
            /* send message to socket client */
            printf("Reply back to socket client...\n");
            snprintf(buf, sizeof(buf), "Hello, socket client [%s:%d]\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
            if( write(client_fd, buf, strlen(buf)) < 0 )
            {
                printf("Reply back to socket client[%d] failure: %s\n", client_fd, strerror(errno));
                close(client_fd);
            }
            printf("\n");
        }
 
        close(client_fd);
    }
 
    close(listen_fd);
    return 0;
}