1+ /* ============================================================================
2+ * Introduction to Operating Systems
3+ * CS 8803, GT OMSCS
4+ *
5+ * Unauthorized copying of this file, via any medium is strictly prohibited.
6+ *
7+ * "echo-server.c"
8+ * Implements the server for "The Echo Protocol" in Problem Set 1.
9+ ============================================================================ */
10+ #include <arpa/inet.h>
11+ #include <ctype.h>
12+ #include <netdb.h>
13+ #include <netinet/in.h>
14+ #include <stdio.h>
15+ #include <stdlib.h>
16+ #include <string.h>
17+ #include <sys/socket.h>
18+ #include <unistd.h>
19+
20+ /* CONSTANTS =============================================================== */
21+ #define SERVER_PORT 8888
22+ #define BUFFER_SIZE 1024
23+
24+ void capitalizeBuffer (char * buffer ) {
25+ do {
26+ * buffer = toupper ((unsigned char ) * buffer );
27+ } while (* buffer ++ );
28+ }
29+
30+ int main (int argc , char * * argv ) {
31+
32+ int socket_fd = 0 ;
33+ int client_socket_fd = 0 ;
34+
35+ char buffer [BUFFER_SIZE ];
36+ int num_bytes = 0 ;
37+
38+ int set_reuse_addr = 1 ; // ON == 1
39+ int max_pending_connections = 1 ;
40+
41+ struct sockaddr_in server ;
42+ struct sockaddr_in client ;
43+ struct hostent * client_host_info ;
44+ char * client_host_ip ;
45+ socklen_t client_addr_len ;
46+
47+ // Create socket (IPv4, stream-based, protocol likely set to TCP)
48+ if (0 > (socket_fd = socket (AF_INET , SOCK_STREAM , 0 ))) {
49+ fprintf (stderr , "server failed to create the listening socket\n" );
50+ exit (1 );
51+ }
52+
53+ // Set socket to use wildcards - i.e. 0.0.0.0:21 and 192.168.0.1:21
54+ // can be bound separately (helps to avoid conflicts)
55+ if (0 != setsockopt (socket_fd , SOL_SOCKET , SO_REUSEADDR , & set_reuse_addr , sizeof (set_reuse_addr ))) {
56+ fprintf (stderr , "server failed to set SO_REUSEADDR socket option (not fatal)\n" );
57+ }
58+
59+ // Configure server socket address structure (init to zero, IPv4,
60+ // network byte order for port and address)
61+ // Address uses local wildcard 0.0.0.0.0 (will connect to any local addr)
62+ bzero (& server , sizeof (server ));
63+ server .sin_family = AF_INET ;
64+ server .sin_addr .s_addr = htonl (INADDR_ANY );
65+ server .sin_port = htons (SERVER_PORT );
66+
67+ // Bind the socket
68+ if (0 > bind (socket_fd , (struct sockaddr * )& server , sizeof (server ))) {
69+ fprintf (stderr , "server failed to bind\n" );
70+ exit (1 );
71+ }
72+
73+ // Listen on the socket for up to some maximum pending connections
74+ if (0 > listen (socket_fd , max_pending_connections )) {
75+ fprintf (stderr , "server failed to listen\n" );
76+ exit (1 );
77+ } else {
78+ fprintf (stdout , "server listening for a connection on port %d\n" , SERVER_PORT );
79+ }
80+
81+ // Get the size client's address structure
82+ client_addr_len = sizeof (client );
83+
84+ // Accept a new client
85+ if (0 > (client_socket_fd = accept (socket_fd , (struct sockaddr * )& client , & client_addr_len )))
86+ {
87+ fprintf (stderr , "server accept failed\n" );
88+ } else {
89+ fprintf (stdout , "server accepted a client!\n" );
90+ }
91+
92+ // Determine who sent the echo so that we can respond
93+ client_host_info = gethostbyaddr ((const char * )& client .sin_addr .s_addr , sizeof (client .sin_addr .s_addr ), AF_INET );
94+ if (client_host_info == NULL ) {
95+ fprintf (stderr , "server could not determine client host address\n" );
96+ }
97+ client_host_ip = inet_ntoa (client .sin_addr );
98+ if (client_host_ip == NULL ) {
99+ fprintf (stderr , "server could not determine client host ip\n" );
100+ }
101+ fprintf (stdout , "server established connection with %s (%s)\n" , client_host_info -> h_name , client_host_ip );
102+
103+ // Read echo from the client
104+ bzero (buffer , BUFFER_SIZE );
105+ num_bytes = read (client_socket_fd , buffer , BUFFER_SIZE );
106+ if (num_bytes == 0 ) {
107+ fprintf (stderr , "server could not read from socket\n" );
108+ } else {
109+ fprintf (stdout , "server received %d bytes: %s\n" , num_bytes , buffer );
110+ }
111+
112+ // Optional: Modifying client message before echo'ing (correctness test)
113+ capitalizeBuffer (buffer );
114+
115+ // Echo back to the client
116+ if (0 > write (client_socket_fd , buffer , strlen (buffer ))) {
117+ fprintf (stderr , "server could not write back to socket\n" );
118+ } else {
119+ fprintf (stdout , "server sending message back to client\n" );
120+ }
121+
122+ // Close the socket and return
123+ close (socket_fd );
124+ return 0 ;
125+ }
0 commit comments