The Socket Interface A Networking Application Program Interface
API: Application Program Interface An API is an interface available to application level programmers to some low level resource or service The interface consists of program elements that the programmer can use in his or her program to access the resource or service These generally consist of data structures and procedures
The Socket Interface Provides a way for one program to establish a network connection with another program Originated in the Berkeley Software Distribution (BSD) version of Unix Provides access to underlying network protocols Patterned after the Unix file system and as much as possible shares features with it Socket interface extended to other environments, in particular Windows
Sockets and TCP/IP The interface is general enough to provide access to multiple protocol stacks We will restrict our attention to its use in accessing the TCP/IP protocols The socket API provides the programmer with system calls for requesting that TCP set up a connection with or that UDP send a message to another program in another machine
Sockets and TCP/IP(cont.) Recall that TCP and UDP are both transport level protocols within the TCP/IP suite TCP provides a connection oriented service –sets up a network connection with another host on the network –monitors packets sent across this connection and provides retransmission of missing packets and reordering of out of order packets –provides reliable disconnection (as much as possible)
Sockets and TCP/IP(cont.) UDP provides a connectionless service –communication consists of isolated packets called datagrams –UDP relies on IP to make a best effort to deliver the packet –UDP provides no acknowledgement, retransmission, or reordering service For TCP the endpoints of a connection and for UDP the source and destination are identified by a host address-port number pair
TCP Sockets:Streams When sockets are used over TCP the sockets are viewed as the endpoints of a bi- directional stream of bytes between the two application programs. Application AApplication B TCP socket TCP socket stream of bytes
TCP Sockets:Streams To send data to the other application the program writes to the socket, to get data from the other application the program reads from the socket Application AApplication B TCP socket TCP socket stream of bytes
TCP Sockets:Streams The socket is required to deliver the bytes to one end in the order they were read from the other end but is not required keep the “message” boundaries intact Application AApplication B TCP socket TCP socket stream of bytes
TCP Sockets:Streams Application A writes “abc” on one write and “def” on a second write When application B does a read it may receive “abcdef” on one read, or “ab” on one read and “cdef” on a second Application AApplication B TCP socket TCP socket f e d b c a
UDP Sockets:Datagrams When sockets are used over UDP the sockets are viewed as endpoints of a bi- directional stream of messages sent between the applications Application AApplication B UDP socket UDP socket msg
UDP Sockets:Datagrams There is no guarantee of delivery. Messages are not necessarily delivered in order Messages are kept intact Application AApplication B UDP socket UDP socket msg
What the Socket Interface Provides The socket interface provides –a data structure for storing protocol information about the source and destination endpoints (for TCP/IP the host addresses and port numbers) –service calls to: obtain the data to be placed in the data structure request a socket from the operating system place the socket in various states required by a client or server send and receive data using the socket close the socket releasing os resources
The Socket Address Data Structures There is a general socket address struct data type named sockaddr This data structure has a very general address field Each specific protocol has its own socket address structure that overlays the address field with its own address structure For TCP/IP this structure type is sockaddr_in (in for internet protocols)
struct sockaddr and struct sockaddr_in sa_len, 1 byte sa_family, 2 bytes sa_data, 14 bytes, the address field sockaddr sockaddr_in sin_len, 1 byte sin_family, 2bytes value is AF_INET sin_port, 2 bytes sin_addr, 4 bytes 8 bytes unused
The Socket Data Structure A socket is identified by a socket descriptor A socket descriptor is an integer This integer is an index into a table of pointers used for files, devices, and sockets The pointer points to a data structure that describes the file, device or socket In the case of a socket this pointer points to a socket structure
The Socket Data Structure protocol family:PF_INET service: SOCK_STREAM or SOCK_DGRAM Local IP Addr Remote IP Addr Local Port Number Remote Port Number ptr. to sock. str. Descriptor Table Socket struct socket descr. = n nth entry in table
The Connection Problem How do two programs connect with each other? In order to connect with each other they must –each know the host address on which the other process is running –each know the port number the other is using –each have set up sockets using these addresses and port numbers –each have made a well timed request to connect to the other
The Client/Server Model: A Solution to the Connection Problem The server is always running, waiting for a connection request at an address and port known to the client The client requests a connection to the server, sending its address and port number The server accepts the connection and communication occurs One end or the other closes the connection
How does the client know? Sometimes the server runs on every machine so the client just needs to know the port number Some services run on well known ports Unix contains service calls to find the address of a host and the port number for a service If the above does not apply the client must be told
Categories of Servers Connection oriented or connectionless –connection oriented, set up a connection –connectionless, just send messages Iterative and concurrent –iterative, can just service one client at a time –concurrent, can service multiple clients simultaneously
Categories of Servers (cont.) Iterative servers should be used when the service time is short, e.g., time of day service Concurrent servers should be used when the service time is long, e.g., telnet or ftp General rule –connection oriented servers are concurrent –iterative servers are connectionless
Categories of Servers (cont.) There are different ways servers can provide concurrency –use the operating systems concurrency mechanism (this is best) –handle the concurrency itself (more complex program)
Model of Iterative Server client socket Server provide service listen for connection client socket client socket
Model of Iterative Server The server establishes a permanent socket using a known port number which it uses to accept connections A client requests a connection to this port number, usually using a dynamically assigned port number The server provides the service on another socket Other clients must wait until connected client has been served
Model of Concurrent Server C Server Client socket listen socket Client socket Client socket Client socket connects communicates Server clone
Model of Concurrent Server The server uses a known socket ( the listen socket in the diagram) which it uses to accept connection requests For each connection request it dynamically creates: – a new server process to provide the service and – a new socket for the client to connect to The service is provided over this new connection After setting up a client the server listens for more connections
Model of Concurrent Server (cont.) The service is provided over this new connection This way it can service multiple clients simultaneously
Socket System Calls socket, allocate a socket and return a socket descriptor identifying the socket connect, establish a connection to the specified endpoint, dynamically allocate a local port no. for the local endpoint bind, bind a particular port no. to the local endpoint (could also bind a particular host address but that is not usually done)
Socket System Calls listen – place the socket in passive listening mode waiting for a request to connect –set a queue length for pending connect requests accept –indicate the process is willing to accept a connection –block the process until a connection is made –allocate a new socket to the connection –return the socket descriptor for the new socket
Socket System Calls close, closes the socket connection and deallocates resources allocated to the socket read –treats data from socket as a byte stream – read data from a socket into a buffer – used in connection oriented situations write –treats data going to socket as a byte stream –write data from a buffer to a socket –used in connection oriented situations
Socket System Calls recv, recvfrom –get a message from the socket –used in connectionless situations send, sendto –send a message out the socket –used in connectionless situations shutdown, shuts down data flow in one direction without closing the socket
Connection Oriented Client/Server System Calls Client –socket –connect –write –read –close Server –socket –bind –listen –accept –read –write –close
Connectionless Client/Server System Calls Client –socket –[connect] –send, sendto –recv,recvfrom –close connect behaves differently in connectionless context Server –socket –bind –recv, recvfrom –send, sendto –close
Getting Information About the Server There are two items of information we generally need to obtain about are server –The address of the machine it is running on –The port number on which the service is offered This information can be obtained by calls to two system routines –gethostbyname, takes the domain name in the form of a string and returns the address
Getting Server Info (cont.) –getservbyname, takes the name of the service as a string and returns the port number The information is returned in a data structure and the functions return pointers to those data structures getservbyname only works for services using well known ports
hostent, The Host Info. Struct struct hostent { char *h_name;//official name of host char **h_aliases; //list of aliases for host int h_addrtype;//hos t address type int h_length;//length of address in bytes char **h_addr_list;//list of addresses from domain //name server }; #define h_addr h_addr_list[0]; //short name for the first address in the list
servent, The Service Struct struct servent { char *s_name;//official service name char **s_aliases; //other aliases int s_port;//port no. for this service char *s_proto;//protocol to use }
More on Getting Server Info Function prototype for gethostbyname struct hostent *gethostbyname(char *hostname); hostAddr=gethostbyname(“bass.csis.gvsu.edu”); Function prototype for getservbyname struct servent *getservbyname(char *servname, char *protname); servPtr=getservbyname(“daytime”, “tcp”);
Command Line Arguments The domain name of the host, the service requested, port number and other aspects of the service can be specified by command line arguments Command line arguments are strings that are typed after the invocation of the program
Command Line Arguments (cont.) Example of using command line arguments %client carp.csis.gvsu.edu echo –client is the name of the program being invoked, this is the first argument –carp.csis.etc. is the name of the host –echo is the name of the service
Command Line Arguments (cont.) Command line arguments are parameters for the main function void main(int argc, char *argv[]) –argc gives the number of command line arguments including the program name –argv is an array of strings consisting of the various command line arguments, argc is the length of the array argv –program name is argv[0], next arg is argv[1], etc.
Command Line Arguments (cont.) %client carp.csis.gvsu.edu echo argc = 3, argv[0] = “client”, argv[1] = carp.csis.gvsu.edu, argv[2] = “echo” struct hostent *hostData; struct servemt *serviceData; hostData = gethostbyname(argv[1]); serviceData = getservbyname(argv[2], “tcp”);
Placing Server Data in Server Address Struct struct hostent * hostData; struct servent *serviceData; struct sockaddr_in serverAddr; memset(&serverAddr, 0, sizeof(serverAddr); serverAddr.sin_family = AF_INET; serverAddr.sin_port = serviceData->s_port; memcopy(&serverAddr.sin_addr, hostData -> h_addr, hostData -> h_length);
Socket System Routines:socket Connless/ConnOr socket, allocates a socket and accompanying struct to hold data about the socket returns a socket descriptor, and integer index into the descriptor table that identifies a pointer to the struct int socket(int family, int type, int protocol); family = PF_INET type = SOCK_STREAM or SOCK_DGRAM protocol = 0 indicates to use default protocol for type
Socket System Routines:socket Connless/ConnOr Examples: sd = socket(PF_INET, SOCK_STREAM, 0); sd = socket(PF_INET, SOCK_DGRAM, 0); The first call will use TCP as the protocol The second call will use UDP as the protocl
Socket System Routines:bind Connless/ConnOr bind, specifies the host address and port no. portion of the socket address structure. –for a client this fixes the address the server responds to during the current session –for a server this fixes the port no. on which the service is offered and to which clients request connection int bind((int socket_descriptor, struct sock_addr &addr, int address_length);
Socket System Routines:bind Connless/ConnOr A connectionless example. Declare variables int sockDescr; struct sockaddr_in server ; Set up address structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = 0;
Socket System Routines:bind Connless/ConnOr Calling the bind function. retVal = bind(sockDescr, (struct sockaddr*) & server, sizeof(server) ); if (retVal < 0) perror(“Error on bind.\n”);
Socket System Routines:close Conless/ConnOr int close(int sockDescr); sockDescr is the socket descriptor for the socket being closed The socket is closed, allocated resources are deallocated returns 0 if successful, -1 if an error the only error is an invalid socket descriptor value
Socket System Routines:sendto Connectionless sendto, sends data from a buffer as a single datagram, address of where to send datagram is included in parameters int sendto(int sockDescr, char *buffer, int bufferSize, (struct sockaddr*) &destAddr, int addrLength); function returns number of bytes sent or -1 as an error condition
Socket System Routines:sendto Connectionless(cont.) sockDescr is the socket descriptor for the socket being used buffer is a buffer containing the data to be sent bufferSize is the number of characters to be sent destAddr is an address structure (sockaddr_in in our case) containing address info. on destination addrLength is size of destAddr structure
Socket System Routines:sendto Connectionless(cont.) Declarations. int sockDescr, bytesSent; struct sockaddr_in server; char buffer[80]; Assume address info on server has been obtained and placed in server structure as in earlier examples strcpy(buffer, “Hello there, Mr./Ms. Server!”);
Socket System Routines:sendto Connectionless(cont.) bytesSent = sendto(sockDescr, buffer, strlen(buffer), (struct sockaddr *) &server, sizeof(server)); if (bytesSent < 0) perror(“Client: Error in sendto.”);
Socket System Routines:recvfrom Connectionless recvfrom, reads a single datagram from a socket into a buffer, surplus data is lost int recvfrom(int sockDescr, char *buffer, int bufferSize, (struct sockaddr*) &srcAddr, int &addrLength); function returns number of bytes read or -1 as an error condition
Socket System Routines:recvfrom Connectionless(cont.) sockDescr is the socket descriptor for the socket being used buffer is a buffer for storing the data read bufferSize is the maximum number of characters to be read srcAddr is an address structure (sockaddr_in in our case) containing address info. on source addrLength is size of srcAddr structure
Socket System Routines:recvfrom Connectionless(cont.) Declarations. int sockDescr, bytesRead, srcAddrLength; struct sockaddr_in source; char buffer[80]; Assume address info on server has been obtained and placed in server structure as in earlier examples strcpy(buffer, “Hello there, Mr./Ms. Server!”
Socket System Routines:recvfrom Connectionless(cont.) bytesRead = recvfrom(sockDescr, buffer, 80, (struct sockaddr *) &source, &srcAddrLength); if (bytesRead < 0) perror(“Client: Error in sendto.”); buffer[bytesRead] = ‘\0’; printf(“Message received: %s\n”, buffer);
Socket System Routines:connect Connection Oriented connect –with SOCK_STREAM/TCP socket connect defines the remote end point of a connection and requests a connection to that endpoint –with SOCK_DGRAM/UDP socket connect simply records the remote endpoint host address and port no. in the socket data structure, subsequently the program can read from or write to the socket without passing the remote address components
Socket System Routines:connect Connection Oriented int connect(int socket_descriptor, struct sock_addr &addr, int address_length); –socket_descriptor is just what it says –&addr is the memory address of a socket address struct which contains the address information for the remote end point –address_length is the length of socket address struct –returns 0 if successful, -1 if not
Socket System Routines:connect Connection Oriented Example: int sockDescr; struct sockaddr_in server ; if (connect(sockDescr, (struct sockaddr *) &server, sizeof(server) ) < 0) { perror(“connect failed\n”); exit(1); }
Socket System Routines:write Connection Oriented int write(int sockDescr, char &buffer, int buffer_length); sockDescr is socket descriptor for socket data is written to buffer is a buffer that contains the data buffer_length is the number of characters to be written from the buffer function returns number of bytes written, -1 if and error
Socket System Routines:write Connection Oriented Example. char buffer[80]; int sockDescr; (Assume socket and connect calls are made) strcpy(buffer, “Hello server!”); if (write(sockDescr, &buffer, strlen(buffer) ) < 0) { perror(“Write failed”); exit(1); }
Socket System Routines:read Connection Oriented int read(int sockDescr, char &buffer, int chars_to_read); sockDescr is socket descriptor for socket data is read from buffer is a buffer that receives the data chars_to_read is the number of characters to be read into the buffer function returns number of bytes read or -1 if an error
Socket System Routines:read Connection Oriented int read(int sockDescr, char &buffer, int chars_to_read); function returns: – number of bytes read for a normal read –0 if other end has closed connection –-1 if an error has occurred
Socket System Routines:read Connection Oriented Example. char buffer[80]; int sockDescr; (Assume socket and connect calls are made) if (numChars = read(sockDescr, &buffer, strlen(buffer) ) < 0) { perror(“read failed”); exit(1); } buffer[numChars] = ‘\0’;
Socket System Routines:accept Connection Oriented accept, used by server, –blocks server until a connection request from a client is received –returns a socket descriptor for a newly allocated socket over which service can be provided int accept(int sockDescr, struct sockaddr *addrPtr, int addrLength);
Socket System Routines:accept Connection Oriented(cont.) Example. newSock = accept(sockDescr, (struct sockaddr*) &server, sizeof(server) ); When accept returns client is connected to the newSock socket The server is now free to perform another accept to get another connection request
Iterative Server’s Use of Accept for ( ; ; ) { newSock = accept(servSock, etc.); /* accept responds to clients connect */ Provide service getting requests an sending responses using newSock when done close(newSock); } Server serves one client at a time
Concurrent Server’s Use of Accept Server calls accept to block and wait for a connection Accept returns socket for providing service Server forks a new process which provides service on this the socket returned by accept Main process cycles back and calls accept again to wait for next connection
Concurrent Server’s Use of Accept for ( ; ; ) { newSock = accept(servSock, etc.); /* accept responds to clients connect */ fork off a child process which Closes servSock Provides service getting requests an sending responses using newSock when done close(newSock) and exit parent process closes newSock } Server serves multiple clients simultaneously