CS 3733 Operating Systems Notes: Network Communication



The client-server model is used in may type sof network communication including mail, ftp, telnet, rlogin, http, and nfs.

In this model, the server waits for requests and the client makes requests for service from the server.

Figure 12.1 (page 433): Multiple clients write requests to a shared one-way communication channel. (Modified to show multiple requests.)

Clients and servers differentiate communication channels using port numbers. A communication endpoint is specified by a host address and a port number. Standard servers use well-known port numbers that allow clients to request services. For example:

In connectionless communication, the client makes a request to an enpoint on a server and the server can respond to the client's endpoint (that is included in the client request). Figure 12.2 (modified from the book) shows two servers and two clients.

Figure 12.2 (page 434, modified): In a connectionless protocol, the server has a well-known port for client requests, but client-specific ports for responses.

In connection-oriented communication, the client sets up a connection using the server's well-known port number and then communicates over a private communications channel as shown in Figure 12.3.

Figure 12.3 (page 434, modified): In a connection-oriented protocol, the server waits for a client request by monitoring a communication endpoint whose address is known to the clients. When a client request arrives, the server creates a new communication endpoint to handle two-way symmetric communication with the client.

If the server needs to handle several concurrent requests, it can do so by forking a chaild to handle each request that comes in.

Figure 12.4 (page 436, modified): The parent-server strategy for client-serveri connection-oriented communication.


UICI: A simple connection-oriented client-server implementation
The server does the following:

A client does the following:
UICI Prototype Description
int u_open(u_port_t port) Creates a TCP socket bound to port.
Returns a file descriptor for the socket.
Returns a negative value on error.
int u_accept(int fd, char *hostn, int hostnsize) Waits for connection request on fd.
Returns communication file descriptor.
On return hostn is first hostnsize-1 characters
of the client's host name.
Returns a negative value on error.
int u_connect(u_port_t port, char *hostn) Initiates connection to server on port port and host hostn.
Returns communication file descriptor.
Returns a negative value on error.
char *u_strerror(int errnum) Returns a string corresponding to an error returned by
u_open, u_accept or u_connect
ssize_t u_read(int fd, void *buf, size_t nbyte) Reads up to nbyte bytes from fd into buf.
Returns -1 on error or the number of bytes actually read.
ssize_t u_write(int fd, void *buf, size_t nbyte) Writes nbyte bytes from buf to fd.
Returns -1 on error or nbyte bytes on success.

u_read and u_write are just like read and write except that they automatically restart if interrupted by a signal and u_write keeps writing bytes until the requested number of bytes have been written.
These can be used with any open file descriptor.

The following figure (not from the book) shows the interaction between a simple UICI server and client.
The server handles a single request with a single response.

The interaction of a UICI client and server.

The copyfile function can be used to copy from one open file descriptor to another. It is similar to the copy_from_network_to_file function of Program 12.1 of the text, but it is simpler because it uses u_read and u_write.

Look at serial and parallel server.

Look at client.

Bidirectional communication: copy2files
Bidirectional client and server: client2 and server2

Network Communication in General

The ISO OSI model: International Standards Organization Open Systems Interconnection reference model.

Figure 12.6, page 446: The ISO model.

Socket Implementation of UICI
The following table shows the socket function needed to implement each UICI function.
UICISockets
u_opensocket
bind
listen
u_acceptaccept
u_connectsocket
connect
u_readread
u_writewrite

All socket system calls return -1 and set errno.
socketcreates a file descriptor
bindassociates a file descriptor with a port and machine
listensets up buffers
acceptwaits for a connection request
connectrequests a connection to a server

#include <sys/types.h>
#include <sys/sicket.h>
int socket(int domain, int type, int protocol);
int bind(int s, const struct sockaddr *address, size_t address_len);
int listen(int s, int backlog);
int accept(int s, struct sockaddr *address, int *address_len);

socket:
domain is AF_UNIX orAF_INET
type is SOCK_STREAM for connection-oriented TCP or SOCK_DGRAM for connectionless UDP
protocol is usually 0

bind:
s is the file descriptor returned by socket
address contains info about the family, port and machine
address_len is the size of the structure used for the address

The format of the address is determined by the address family (domain).
For AF_INET it is a struct sickaddr_in which is defined as follows:

struct sockaddr_in {
        sa_family_t     sin_family;
        in_port_t       sin_port;
        struct  in_addr sin_addr;
        char            sin_zero[8];
};

listen:
This is used to set the number of unaccepted outstanding requests.

We can now look at the implementation of u_open.

accept:
This waits for a connection request.
s: from the socket call.
address: filled in with information about the client making a connection request.
address_len: You fill this in with the size of the address buffer you provided.

To convert the info in address to a machine name you can use:
struct hostent *gethostbyaddr(const void *addr, size_t len, int type);

We can now look at the implementations of u_accept and u_connect.

We can also look at u_read and u_write.

A tar file of the programs from these notes is available here.