Sockets CIS 370 Lab 10 UMass Dartmouth
Introduction 4 Sockets provide a simple programming interface which is consistent for processes on the same machine or across different machines. 4 The aim of UNIX sockets is to provide a means of IPC that is sufficiently generic to allow bi-directional messages between two processes irrespective of where they reside.
General Information 4 For any communication to take place between processes, the machines on which they are running must be connected. –Hardware level: network equipment such as cables, cards and devices such as routers. –Software level: by a standard set of network protocols. 4 Simplest IPC model is client-server. –Server is a process which provides a service. –Client is a process (possibly on another host) that connects to the server to invoke its service.
Types of Communication 4 Processes that send messages across a network can choose one of two ways to communicate. –The connection-oriented model (virtual circuit). Uses TCP – CIS475 (Computer Networks). –The connectionless-oriented model. Uses UDP – CIS475 (Computer Networks).
The Connection-Oriented Model 4 The connection-oriented model can be used by a process which needs to send an unformatted, uninterrupted stream of characters to the same constant destination. 4 For example: a remote login connection where a client system has a virtual connection to a server. 4 Like a phone network.
The Connectionless Model 4 Suppose a server wants to send a broadcast message to all its clients (and is not necessarily concerned that the clients get the message), the server can use a connectionless-oriented model. 4 The process sends the message to a specified network address, it then sends the next message to a different address. 4 Like United States Postal Service.
Addressing 4 When processes are communicating across a network they must know the network address of the machine that the processes are residing on. 4 The address essentially gives the physical location of a machine on a network. 4 Addresses are generally layered, representing the different levels of a network.
IP Addressing –Across the world’s networks there is an almost universally accepted addressing standard - IP internet addressing. –An IPv4 address consists of four decimals separated by periods uranium’s (current) IP address. –At the programming level, IP addresses are stored in an in_addr_t type.
IP Addressing UNIX provides the inet_addr() system call that converts the four-decimal representation to the in_addr_t representation. 4 Usage #include in_addr_t inet_addr(const char *ip_address); *ip_address is in the form discussed earlier, the routine returns an address in the form of in_addr_t (a -1 if in error).
Ports 4 Once the address of the machine to access is known, the client process also needs to know the correct server processes to connect to. 4 Each server process sets and listens for connections on a specified port number. 4 Therefore a client process will ask for a connection to a specific machine and port.
Ports At the programming level, ports are stored as an in_port_t type. 4 UNIX systems expect a port to be a 16-byte unsigned int. –Our lab machines are 32-bit systems, so integers are 4 bytes. Need to convert! #include uint16_t htons(uint16_t hostshort); Ex: in_port_t serverPortNum = htons(7000);
Sockets 4 In all forms of communication, both the client and server must establish their own transport end points, or sockets. –Like a wall socket: can’t get electricity to a lamp’s plug without a socket! 4 These are handles used to establish a link between processes across a network. 4 Different types of sockets are used for different types of IPC within the same machine or on different machines.
Sockets 4 A specific form of socket for network communication is shown below: #include struct sockaddr_in{ sa_family_t sin_family;// internet address family in_port_t sin_port;// port number struct in_addrsin_addr;// holds the IP address } Creation of sockets is achieved using the socket() system call.
#include int socket(int domain, int type, int protocol); domain tells the call where the socket is to be used. –AF_INET - internet domain. –AF_UNIX - same UNIX machine. type specifies connection type. –SOCK_STREAM - TCP. –SOCK_DGRAM - UDP. protocol indicates type of communication. –SOCK_STREAM - TCP. –SOCK_DGRAM - UDP. 4 Returns a file descriptor for the socket.
Server-Side Binding The bind() system call associates the true network address of a machine with a socket identifier. #include int bind(int sockfd, const struct sockaddr *address, size_t add_len); sockfd is the socket file descriptor, returned by the socket() system call. *address is a pointer to a socket address structure. add_len is the size of the socket structure referenced by address. 4 Returns 0 on success, -1 on failure.
Server-Side Listening 4 After binding and before any client system can connect to the newly created server endpoint, the server must set itself up to wait for connections. #include int listen (int sockfd, int queue_size); sockfd is the socket file descriptor. queue_size is the number of incoming connection requests that the server can queue.
Server-Side Accepting When the server receives a connect() request from a client (discussed later) it has to create an entirely new socket to handle the specific communication. 4 The first socket is used only to establish a connection. Data isn’t passed through it. Creation of a second socket is done using the accept() system call.
#include int accept(int sockfd, struct sockaddr *address, size_t *add_len); sockfd is the original socket file descriptor. *address is a pointer to a socket address structure. Since we already have this info from the original socket, can set to NULL. add_len holds the size of the socket structure referenced by address. Can also be NULL. 4 Returns a file descriptor to the new socket to be used for communication (-1 on failure).
A Simple Example 4 We will use all the system calls we have seen so far. 4 Server doesn’t actually do anything yet except establish itself on a socket and wait for a client connection.
Client-Side Connecting to Server To request a connection to a server process and machine, the client uses the connect() system call. Once the server receives this request, it will reply with its own accept() request.
#include int connect(int c_sockfd, const struct sockaddr *address, size_t add_len); c_sockfd is the client’s socket file descriptor. *address is a pointer to a socket address structure. This should contain the IP address and port number of the server to connect to. add_len holds the size of the socket structure referenced by address. 4 Returns 0 on successful connection to server, -1 on failure.
The Other Half of the Example 4 Client simply sends a connection request to the server. –The client MUST know the internet address of the server in order to connect!
Sending and Receiving Data 4 Now a connection has been established between the client and the server. We’re finally ready to communicate for IPC! 4 Remember, sockets have file descriptors associated with them. –Hopefully you recall from earlier labs that we can read() and write() with file descriptors. 4 If extra options are needed, two new system calls can be used instead. – send() and recv().
send() #include ssize_t send(int sockfd, const void *buffer, size_t length, int flags); sockfd is the socket file descriptor. *buffer contains the message to send. length is the size of the buffer. flags are optional parameters. We aren’t doing anything fancy, so these can be 0. –This causes the behavior of send() to be identical to write() ! ssize_t recv(int sockfd, void *buffer, size_t length, int flags); 4 The recv call specifies the file descriptor to read the data from the buffer and the length of the buffer.
recv() #include ssize_t recv(int sockfd, void *buffer, size_t length, int flags); sockfd is the socket file descriptor. *buffer contains the destination of the received message. length is the size of buffer. flags can be 0. –This causes the behavior of recv() to be identical to read() ! 4 The recv call specifies the file descriptor to read the data from the buffer and the length of the buffer.
Continuing Our Example 4 Let’s look at a complete example. –Client accepts a lowercase character from user at command line. –Client sends lowercase letter to server. –Server will convert the letter to uppercase and send it back to client. –Client will then output the new character to user. *Note that the user does not interact directly with the server!
Closing the Connection 4 It is important to deal with closing the socket connection. 4 Since a socket is a two-way communication mechanism, it is impossible to predict whether a process will be trying to read or write when a break in the communication occurs.
If a process attempts to write() or send() data to a socket which has become disconnected it will receive the SIGPIPE signal, which can be dealt with through a signal handler. If read() or recv() returns zero, then the connection has been closed by the other side. 4 If using the connection-oriented model, the socket close is blocked until the current data transfer is complete. 4 If the connectionless model is in use, the socket is closed immediately. Closing the Connection
Completing Our Example 4 Client and server both close their sockets if the other process dies. 4 For completeness, some things have been changed from previous examples. –Client supports multiple input characters. –Server now supports multiple clients. 4 Following complete samples are available online:
The Connectionless Model 4 Up to this point, we’ve looked only at the connection-oriented model. 4 The remaining slides are for educational purposes only and are optional. 4 The following slides are NOT necessary for completing today’s assignment!
The Connectionless Model 4 Unlike the connection-oriented approach, packets transmitted between the client and server will arrive at their destination in an indeterminate order. A process wishing to send or receive messages across a network must create its own local socket and bind() its own network address to that socket. –This means clients need to bind() too!
Sending and Receiving Messages 4 In the connectionless model, the processes aren’t directly connected to eachother. 4 Processes can send/recv data from any process on any machine. –This is how the Internet works! 4 Processes don’t automatically know who is sending messages to them. –Cannot use send() and recv() !
ssize_t sendto(int sockfd, const void *message, size_t length, int flags,struct sockaddr *send_addr, size_t *add_len); sockfd is the socket file descriptor. *message contains the data to send. length is the size of message. flags can be 0. *send_addr contains the information of the recipient including its IP address and port number. *add_len is the size of send_addr.
ssize_t recvfrom(int sockfd, void *message, size_t length, int flags, struct sockaddr *send_addr, size_t *add_len); sockfd is the socket file descriptor. *message is the buffer for received data. length is the size of message. flags can be 0. *send_addr contains the information of the sender including its IP address and port number. *add_len is the size of send_addr.
The Difference? 4 In both models the server has to create a socket and bind its local address to that socket. 4 In the connection model the server must then start to listen for the incoming connection. This step is not necessary in the connectionless model as the client will do more of the work.
The Difference? 4 From a client perspective, in the connection model, the client just connects to the server. 4 In the connectionless model, the client must create a socket and bind its local address to that socket.
The Difference? 4 Different system calls are normally used to transmit data. The sendto() and recvfrom() calls are normally used in the connectionless model so that the server can retrieve information about the sender of the message and reply accordingly.