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

Last change on this file since 660 was 660, checked in by alain, 4 years ago

introducing three applications:

  • kleenex
  • tcp_client
  • tcp_server
File size: 4.9 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[server] receive error => return to main\n" );
43            return;
44        }
45        else if( nbytes == 0 )
46        {
47            printf("\n\n[server] receive 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            return;
64        }
65
66        // send server message
67        nbytes = send( fdid , buffer , size , 0 ) ;
68
69        if( nbytes != size )
70        {
71            printf("\n[server] send error => chat return to main\n" );
72            return;
73        }
74    }  // end chat loop
75
76}  // end server_chat()
77
78
79////////////////
80int main( void )
81{
82    int                  pid;          // process pid
83    int                  listen_fdid;  // listen socket identifier
84    int                  chat_fdid;    // chat socket identifier
85    int                  error;
86
87    struct sockaddr_in   server_sin;   // server socket IP address
88    struct sockaddr_in   client_sin;   // client socket IP address
89
90    unsigned long long   start_cycle;
91
92    int                  addr_length = sizeof(sockaddr_t);
93
94    // get  start cycle
95    get_cycle( &start_cycle );
96
97    pid = getpid();
98
99    printf("\n[server] starts at cycle %d\n",
100    (unsigned int)start_cycle );
101
102    // 1. create TCP socket
103    listen_fdid = socket( AF_INET,
104                        SOCK_STREAM,
105                        0 );
106
107    if( listen_fdid < 0 )
108    {
109        printf("\n[server error] cannot create socket\n");
110        exit( 0 );
111    }
112    else
113    {
114        printf("\n[server] created socket[%x,%d]\n", pid, listen_fdid );
115    }
116
117    // 2. bind local socket
118    server_sin.sin_domain = HTONS( AF_INET );
119    server_sin.sin_addr   = HTONL( LOCAL_ADDR );
120    server_sin.sin_port   = HTONS( LOCAL_PORT );
121
122    error = bind( listen_fdid,
123                  (sockaddr_t *)(&server_sin),
124                  sizeof(sockaddr_t) );
125    if( error )
126    {
127        printf("\n[server error] bind failure for socket[%x,%d]\n",
128        pid, listen_fdid );
129        exit( 0 );
130    }
131    else
132    {
133        printf("\n[server] listening socket[%x,%d] bound : [%x,%x]\n",
134        pid, listen_fdid, server_sin.sin_addr, server_sin.sin_port );
135    }
136
137    // 3. Listen clients connection requests
138    error = listen( listen_fdid , MAX_PENDING_CONNECT );
139                     
140    if( error )
141    {
142        printf("\n[server error] listen failure for socket[%x,%d]\n",
143        pid, listen_fdid );
144        exit( 0 );
145    }
146    else
147    {
148        printf("\n[server] listening socket[%x,%d] waiting connection request\n",
149        pid, listen_fdid );
150    }
151
152   
153    // 4. accept connection(s)
154    chat_fdid = accept( listen_fdid,
155                        (sockaddr_t *)&client_sin,
156                        &addr_length );
157
158    if( chat_fdid == -1 )
159    {
160        printf("\n[server error] accept failure on socket[%x,%d]\n",
161        pid, listen_fdid );
162        exit( 0 );
163    }
164    else
165    {
166        printf("\n[server] chat socket[%x,%d] accepted client [%x,%x]\n",
167        pid, chat_fdid , client_sin.sin_addr , client_sin.sin_port );
168    }
169
170    // 5. call chat function
171    // server_chat( chat_fdid );
172
173    // 6. close listen and chat sockets
174
175    printf("\n[server] before close socket[%x,%d]\n", pid, chat_fdid );
176
177    close( chat_fdid );
178
179    printf("\n[server] after close socket[%x,%d]\n", pid, chat_fdid );
180
181    close( listen_fdid );
182
183    printf("\n[server] closed both <listen> & <chat> sockets\n" );
184
185    exit(0);
186
187    return 0;
188}
Note: See TracBrowser for help on using the repository browser.