/////////////////////////////////////////////////////////////////////////////////////// // file : tcp_server.c // author : Alain Greiner // date : march 2020 /////////////////////////////////////////////////////////////////////////////////////// // This file describes a single thread TCP server chat application. // The client send the first message. /////////////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #define BUF_SIZE 256 #define MAX_PENDING_CONNECT 16 #define LOCAL_PORT 13 #define LOCAL_ADDR 0xBBBBBBBB //////////////////////////// void server_chat( int fdid ) { char buffer[BUF_SIZE]; // string buffer (for send and receive) int size; // string length (including NUL) int nbytes; // number of characters actually sent or received // chat loop while( 1 ) { // display client prompt printf("\n[from client] "); // get client message nbytes = recv( fdid, buffer, BUF_SIZE, 0 ); if( nbytes < 0 ) { printf("\n\n[server] receive error => return to main\n" ); return; } else if( nbytes == 0 ) { printf("\n\n[server] receive EOF => return to main\n" ); return; } // display client message printf("%s\n", buffer ); // display server prompt printf("\n[from server] "); // build server message size = get_string( buffer , BUF_SIZE ); // exit chat function when local message is the "exit" string if( strncmp( "exit" , buffer , 4 ) == 0 ) { return; } // send server message nbytes = send( fdid , buffer , size , 0 ) ; if( nbytes != size ) { printf("\n[server] send error => chat return to main\n" ); return; } } // end chat loop } // end server_chat() //////////////// int main( void ) { int pid; // process pid int listen_fdid; // listen socket identifier int chat_fdid; // chat socket identifier int error; struct sockaddr_in server_sin; // server socket IP address struct sockaddr_in client_sin; // client socket IP address unsigned long long start_cycle; int addr_length = sizeof(sockaddr_t); // get start cycle get_cycle( &start_cycle ); pid = getpid(); printf("\n[server] starts at cycle %d\n", (unsigned int)start_cycle ); // 1. create TCP socket listen_fdid = socket( AF_INET, SOCK_STREAM, 0 ); if( listen_fdid < 0 ) { printf("\n[server error] cannot create socket\n"); exit( 0 ); } else { printf("\n[server] created socket[%x,%d]\n", pid, listen_fdid ); } // 2. bind local socket server_sin.sin_domain = HTONS( AF_INET ); server_sin.sin_addr = HTONL( LOCAL_ADDR ); server_sin.sin_port = HTONS( LOCAL_PORT ); error = bind( listen_fdid, (sockaddr_t *)(&server_sin), sizeof(sockaddr_t) ); if( error ) { printf("\n[server error] bind failure for socket[%x,%d]\n", pid, listen_fdid ); exit( 0 ); } else { printf("\n[server] listening socket[%x,%d] bound : [%x,%x]\n", pid, listen_fdid, server_sin.sin_addr, server_sin.sin_port ); } // 3. Listen clients connection requests error = listen( listen_fdid , MAX_PENDING_CONNECT ); if( error ) { printf("\n[server error] listen failure for socket[%x,%d]\n", pid, listen_fdid ); exit( 0 ); } else { printf("\n[server] listening socket[%x,%d] waiting connection request\n", pid, listen_fdid ); } // 4. accept connection(s) chat_fdid = accept( listen_fdid, (sockaddr_t *)&client_sin, &addr_length ); if( chat_fdid == -1 ) { printf("\n[server error] accept failure on socket[%x,%d]\n", pid, listen_fdid ); exit( 0 ); } else { printf("\n[server] chat socket[%x,%d] accepted client [%x,%x]\n", pid, chat_fdid , client_sin.sin_addr , client_sin.sin_port ); } // 5. call chat function // server_chat( chat_fdid ); // 6. close listen and chat sockets printf("\n[server] before close socket[%x,%d]\n", pid, chat_fdid ); close( chat_fdid ); printf("\n[server] after close socket[%x,%d]\n", pid, chat_fdid ); close( listen_fdid ); printf("\n[server] closed both & sockets\n" ); exit(0); return 0; }