source: trunk/user/tcp_server/tcp_server.c @ 676

Last change on this file since 676 was 676, checked in by alain, 3 years ago

Introduce chat application to test the named pipes.

File size: 4.8 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////////
2//  file   : tcp_server.c
3//  author : Alain Greiner
4//  date   : march 2020
5///////////////////////////////////////////////////////////////////////////////////////
6//  This file describes a single thread TCP server chat application.
7//  The client send the first message.
8///////////////////////////////////////////////////////////////////////////////////////
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <almosmkh.h>
14#include <unistd.h>
15#include <sys/socket.h>
16
17#define   BUF_SIZE             256
18
19#define   MAX_PENDING_CONNECT  16
20
21#define   LOCAL_PORT           13
22#define   LOCAL_ADDR           0xBBBBBBBB
23
24////////////////////////////
25void server_chat( int fdid )
26{
27    char   buffer[BUF_SIZE];   // string buffer (for send and receive)
28    int    size;               // string length (including NUL)
29    int    nbytes;             // number of characters actually sent or received
30
31    // chat loop
32    while( 1 )
33    {
34        // display client prompt
35        printf("\n[from client] ");
36
37        // get client message
38        nbytes = recv( fdid, buffer, BUF_SIZE, 0 );
39
40        if( nbytes < 0 )
41        {
42            printf("\n\n[tcp_server error] cannot receive => return to main\n" );
43            return;
44        }
45        else if( nbytes == 0 )
46        {
47            printf("\n\n[tcp_server stop] received EOF => return to main\n" );
48            return;
49        }
50
51        // display client message
52        printf("%s\n", buffer );
53
54        // display server prompt
55        printf("\n[from server] ");
56
57        // build server message
58        size = get_string( buffer , BUF_SIZE );
59
60        // exit chat function when local message is the "exit" string
61        if( strncmp( "exit" , buffer , 4 ) == 0 )
62        {
63            printf("\n[tcp_server stop] local message is <exit> => return to main\n" );
64            return;
65        }
66
67        // send server message
68        nbytes = send( fdid , buffer , size , 0 ) ;
69
70        if( nbytes != size )
71        {
72            printf("\n[tcp_server error] cannot send => return to main\n" );
73            return;
74        }
75    }  // end chat loop
76
77}  // end server_chat()
78
79
80////////////////
81int main( void )
82{
83    int                  pid;          // process pid
84    int                  listen_fdid;  // listen socket identifier
85    int                  chat_fdid;    // chat socket identifier
86    int                  error;
87
88    struct sockaddr_in   server_sin;   // server socket IP address
89    struct sockaddr_in   client_sin;   // client socket IP address
90
91    unsigned long long   start_cycle;
92
93    int                  addr_length = sizeof(sockaddr_t);
94
95    // get  start cycle
96    get_cycle( &start_cycle );
97
98    pid = getpid();
99
100    printf("\n[tcp_server] starts at cycle %d\n",
101    (unsigned int)start_cycle );
102
103    // 1. create TCP socket
104    listen_fdid = socket( AF_INET,
105                        SOCK_STREAM,
106                        0 );
107
108    if( listen_fdid < 0 )
109    {
110        printf("\n[tcp_server error] cannot create socket\n");
111        exit( 0 );
112    }
113    else
114    {
115        printf("\n[tcp_server] created socket[%x,%d]\n", pid, listen_fdid );
116    }
117
118    // 2. bind local socket
119    server_sin.sin_domain = HTONS( AF_INET );
120    server_sin.sin_addr   = HTONL( LOCAL_ADDR );
121    server_sin.sin_port   = HTONS( LOCAL_PORT );
122
123    error = bind( listen_fdid,
124                  (sockaddr_t *)(&server_sin),
125                  sizeof(sockaddr_t) );
126    if( error )
127    {
128        printf("\n[tcp_server error] bind failure for socket[%x,%d]\n",
129        pid, listen_fdid );
130        exit( 0 );
131    }
132
133    printf("\n[tcp_server] listening socket[%x,%d] bound : [%x,%x]\n",
134    pid, listen_fdid, server_sin.sin_addr, server_sin.sin_port );
135
136    // 3. Listen clients connection requests
137    error = listen( listen_fdid , MAX_PENDING_CONNECT );
138                     
139    if( error )
140    {
141        printf("\n[tcp_server error] listen failure for socket[%x,%d]\n",
142        pid, listen_fdid );
143        exit( 0 );
144    }
145
146    printf("\n[tcp_server] listening socket[%x,%d] waiting connection request\n",
147    pid, listen_fdid );
148   
149    // 4. accept connection(s)
150    chat_fdid = accept( listen_fdid,
151                        (sockaddr_t *)&client_sin,
152                        &addr_length );
153
154    if( chat_fdid < 0 )
155    {
156        printf("\n[tcp_server error] accept failure on socket[%x,%d]\n",
157        pid, listen_fdid );
158        exit( 0 );
159    }
160
161    printf("\n[tcp_server] chat socket[%x,%d] accepted client [%x,%x]\n",
162    pid, chat_fdid , client_sin.sin_addr , client_sin.sin_port );
163
164    // 5. call chat function
165    server_chat( chat_fdid ); 
166
167    // 6. close listen and chat sockets
168    close( chat_fdid );
169    close( listen_fdid );
170
171    printf("\n[tcp_server] closed both <listen> & <chat> sockets\n" );
172
173    exit(0);
174
175    return 0;
176}
Note: See TracBrowser for help on using the repository browser.