CS 360 Intro to Socket Programming Two views: Server vs. Client Servers LISTEN for a connection and respond when one is made Usually, server processes are not programmed to exit and are frequently called “daemons”. They “listen” for an incoming connection on a particular PORT number. Ports 0 through 1023 are preassigned and require root privileges to listen to. Ports >1023 are termed ephemeral (mostly not preassigned). Usually, when a connection is made to a server, it forks off a child process which responds to the client while the parent listens for another connection. Clients actively make a connection to a server An Internet address (xxx.xxx.xxx.xxx) and a port number are selected by the client. It then attempts to connect to that host/port number If the connection succeeds, it proceeds to read and write data through its connection. For our purposes, we will only use TCP (no UDP) Reliable, connection-oriented protocol Page 2 CS 360, WSU Vancouver Server side programming Synopsis: Make a socket using socket() Bind the socket to a port number using bind() to give it an “address” on the net Call listen() to establish our process as a server. – However, listen() does not actually listen Page 3 Wait for a completed connection to be established with accept() When a connection is accepted, use fork() to create a child process The parent closes child’s socket and loops back to accept another connection The child process services the client connection and eventually exits. At some point the parent should use waitpid() to prevent “zombie” processes CS 360, WSU Vancouver Important header files Generally, you will need to include the following header files: sys/types.h sys/socket.h netinet/in.h arpa/inet.h netdb.h An important type that holds the data associated with an Internet address: struct sockaddr_in { } length AF_INET 16 bit port number 32 bit IP version 4 address Unused Page 4 CS 360, WSU Vancouver Make a socket int listenfd; listenfd = socket(AF_INET, SOCK_STREAM, 0); • AF_INET is the domain -> Internet •SOCK_STREAM is the protocol family (TCP) •If the result is < 0, there is an error, use perror() to print the message Page 5 CS 360, WSU Vancouver Bind the socket to a port #define MY_PORT_NUMBER 49999 struct sockaddr_in servAddr; memset(&servAddr, 0, sizeof(servAdder)); servAddr.sin_family = AF_INET; servAddr.sin_port = htons(MY_PORT_NUMBER); servAddr.sin_addr.s_addr = htonl(INADDR_ANY); if ( bind( listenfd, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) { perror(“bind”); exit(1); } Page 6 CS 360, WSU Vancouver Listen and Accept connections listen( listenfd, 1) • Sets up a connection queue one level deep int connectfd; int length = sizeof(struct sockaddr_in); struct sockaddr_in clientAddr; connectfd = accept(listenfd, (struct sockaddr *) &clientAddr, &length); • Waits (blocks) until a connection is established by a client • When that happens, a new descriptor for the connection is returned • If there is an error the result is < 0; • The client’s address is written into the sockaddr structure Page 7 CS 360, WSU Vancouver Getting a text host name struct hostent* hostEntry; char* hostName; hostEntry = gethostbyaddr(&(clientAddr.sin_addr), sizeof(struct in_addr), AF_INET); hostName = hostEntry->h_name; Uses DNS to convert a numerical Internet address to a host name Returns NULL if there is an error, use herror() to print the error message, it has the same argument as perror() Page 8 CS 360, WSU Vancouver Making a connection from a client int socketfd; socketfd = socket( AF_INET, SOCK_STREAM, 0); Make an Internet socket using TCP protocol Same as server code Page 9 CS 360, WSU Vancouver Set up the address of the server struct sockaddr_in servaddr; struct hostent* hostEntry; struct in_addr **pptr; memset( &servAddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(MY_PORT_NUMBER); hostEntry = gethostbyname(“lx.encs.vancouver.wsu.edu”); /* test for error using herror() */ /* this is magic, unless you want to dig into the man pages */ pptr = (struct in_addr **) hostEntry->h_addr_list; memcpy(&servAddr.sin_addr, *pptr, sizeof(struct in_addr)); Plug in the family and port number Get the numeric form of the server address Copy it into the address structure Page 10 CS 360, WSU Vancouver Connect to the server connect(socketfd, (struct sockaddr *) &servAddr, sizeof(servAddr)); A connection is established, after which I/O may be performed on socketfd This is the file I/O equivalent of “open()” Or, there is an error which is indicated by the return being < 0 Page 11 Always check for an error… CS 360, WSU Vancouver Socket I/O Use Unix read() and write() using the descriptor for the connected socket in the same manner as file I/O. EXCEPT: Read operations on a socket may return less than the requested number of bytes (in the manner of reading from a pipe). This is NOT an indication of the last block of data. Continue reading until the number of bytes read is zero (implying EOF). Just like I/O with pipes except socket descriptors are bi-directional Always test for errors on reads or writes Use use the Unix netstat utility in the shell to observe open ports, established connections, etc. Page 12 CS 360, WSU Vancouver Lab Assignment Write two programs daytime.c dayserve.c dayserve is a server process that listens on an ephemeral TCP port for one connection. When it receives a connection, it logs the hostname of the client to stdout and writes the current date and time to the client via the socket connection. See library routines time() and ctime() to obtain and format the time of day Suggestion: start by writing some string of your own choosing to the client daytime is a client program that takes one argument on the command line. That argument is the server’s host name or IP address (in dotted decimal). It makes a TCP connection to the indicated host and dayserve’s port number (or indicates the error, if it cannot) and then writes the information received from dayserve to stdout. Use port number 49999 (that way you can communicate with each other ’s servers) Demonstrate your client and server programs in lab by the end of lab on Friday, April 17th. Submit the following files by email by the end of the day: daytime.c dayserve.c You will need this code and these capabilities for the final project so you would be wise to modularize/encapsulate them for subsequent re-use. Page 13 CS 360, WSU Vancouver