2015-01-09 13:21:07 -07:00
|
|
|
/* A simple server in the internet domain using TCP
|
|
|
|
The port number is passed as an argument */
|
|
|
|
|
|
|
|
// From:
|
|
|
|
// http://www.linuxhowtos.org/C_C++/socket.htm
|
2015-01-20 11:17:36 -07:00
|
|
|
// commented for reference
|
2015-01-09 13:21:07 -07:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
|
|
|
void error( const char *msg )
|
|
|
|
{
|
|
|
|
perror( msg );
|
|
|
|
exit( 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
int main( int argc, char *argv[] )
|
|
|
|
{
|
|
|
|
// VARIABLE DEFINITONS
|
|
|
|
|
|
|
|
// file descriptors
|
|
|
|
int sockfd; // returned by socket system call
|
|
|
|
int newsockfd; // returned by accept system call
|
|
|
|
|
|
|
|
int portno; // stores port number (passed as argument)
|
|
|
|
socklen_t clilen; // stores the size of the client address. needed for the accept system call
|
|
|
|
char buffer[ 256 ]; // server reads characters from socket connection into buffer
|
|
|
|
|
|
|
|
// sockaddr_in is defined in "netinet/in.h"
|
|
|
|
struct sockaddr_in serv_addr; // serv_addr contains the server address
|
|
|
|
struct sockaddr_in cli_addr; // cli_addr contains the client address
|
|
|
|
|
|
|
|
int n; // return value for read/write calls (contains the # of characters read/written)
|
|
|
|
|
|
|
|
// BEGIN REAL CODE
|
|
|
|
|
|
|
|
// Check that there are enough arguments
|
|
|
|
if( argc < 2 )
|
|
|
|
{
|
|
|
|
fprintf( stderr, "ERROR, no port provided\n" );
|
|
|
|
exit( 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
// socket system call creates new socket
|
|
|
|
// arg0: address domain ( Unix domain [AF_UNIX] or Internet domain [AF_INET] )
|
|
|
|
// arg1: socket type ( Stream [SOCK_STREAM] or Datagram [SOCK_DGRAM] )
|
|
|
|
// arg2: protocol ( 0 lets system decide best protocol: TCP for streams, UDP for datagrams )
|
|
|
|
// returns file descriptor on success
|
|
|
|
// returns -1 on failure
|
|
|
|
sockfd = socket( AF_INET, SOCK_STREAM, 0 );
|
|
|
|
if( sockfd < 0 ) // on error: sockfd = -1
|
|
|
|
error( "ERROR opening socket" );
|
|
|
|
|
|
|
|
// bzero sets all values in a buffer to zero
|
|
|
|
// arg0: pointer to buffer
|
|
|
|
// arg1: length of buffer
|
|
|
|
bzero( (char*) &serv_addr, sizeof( serv_addr ) ); // initializes serv_addr to all zeroes
|
|
|
|
|
|
|
|
// atoi converts a string of digits to an integer
|
|
|
|
portno = atoi( argv[ 1 ] );
|
|
|
|
|
|
|
|
serv_addr.sin_family = AF_INET; // sin_family should always be set to symbolic constant AF_INET
|
|
|
|
serv_addr.sin_addr.s_addr = INADDR_ANY; // sin_addr.s_addr contains the IP address of the host. INADDR_ANY is a symbolic constant which get this address
|
|
|
|
serv_addr.sin_port = htons( portno ); // sin_port contains the port number. htons converts a port number in host byte order to network byte order
|
|
|
|
|
|
|
|
// bind system call binds a socket to an address ( address = address of host & port number)
|
|
|
|
// arg0: socket file descriptor
|
|
|
|
// arg1: pointer to structure of type sockaddr. what is passed is a structure of type sockaddr_in, must be cast to correct type
|
|
|
|
// arg2: size of structure &arg1
|
|
|
|
// returns 0 on success ?????????
|
|
|
|
if( bind( sockfd, ( struct sockaddr* ) &serv_addr, sizeof( serv_addr ) ) < 0 )
|
|
|
|
error( "ERROR on binding" );
|
|
|
|
|
|
|
|
// listen system call allows program to listen to socket for connections
|
|
|
|
// arg0: file descriptor of socket
|
|
|
|
// arg1: size of backlog queue (maximum number of connections which can be waiting while handling any specific connection) (standard: 5)
|
|
|
|
listen( sockfd, 5 );
|
|
|
|
|
|
|
|
// set client address length to the size of client's address
|
|
|
|
clilen = sizeof( cli_addr );
|
|
|
|
|
|
|
|
// accept system call causes the program to stop until a client connects to the server
|
|
|
|
// arg0: file descriptor of the socket
|
|
|
|
// arg1: pointer for the client address structure
|
|
|
|
// arg2: size of structure &arg1
|
|
|
|
// returns a file descriptor for the connection on success
|
|
|
|
// returns -1 on failure ?????
|
|
|
|
newsockfd = accept( sockfd, (struct sockaddr *) &cli_addr, &clilen );
|
|
|
|
if( newsockfd < 0 )
|
|
|
|
error( "ERROR on accept" );
|
|
|
|
|
|
|
|
bzero( buffer, 256 ); // clear the receive buffer
|
|
|
|
|
|
|
|
// read system call reads from socket
|
|
|
|
// read will block the program until there is something to read
|
|
|
|
// arg0: file descriptor for the connection (NOTE: this is the new one returned by accept)
|
|
|
|
// arg1: buffer to put characters into
|
|
|
|
// arg2: maximum number of character to read and put in buffer
|
|
|
|
// return number of characters read on success
|
|
|
|
// return -1 on failure ?????
|
|
|
|
n = read( newsockfd, buffer, 255 );
|
|
|
|
if ( n < 0 )
|
|
|
|
error("ERROR reading from socket");
|
|
|
|
|
|
|
|
// buffer will contain the message now
|
|
|
|
printf( "Here is the message: %s\n", buffer );
|
|
|
|
|
|
|
|
// write system call writes to socket
|
|
|
|
// arg0: file descriptor for the connection (NOTE: again, this is the new one returned by accept)
|
|
|
|
// arg1: pointer to character (char*)
|
|
|
|
// arg2: length of &arg1
|
|
|
|
// return number of characters written on success
|
|
|
|
// return -1 on failure
|
|
|
|
n = write( newsockfd, "I got your message", 18 );
|
|
|
|
if ( n < 0 )
|
|
|
|
error( "ERROR writing to socket" );
|
|
|
|
|
|
|
|
// when socket is no longer needed, close the connection
|
|
|
|
close( newsockfd );
|
|
|
|
close( sockfd );
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|