Unit-6 Elementary TCP Sockets
Unit-6 Elementary TCP Sockets
Source: UNIX Network Programming: Chapter: 4 W. Richard Stevens, Bill Fenner, Andrew M. Rudoff
Sockets
● A communication structure
● Acts as an end point
● Two processes need a socket at each end to communicate with each other
● A socket is defined in the operating system as a structure
4
Socket Structure Fields
Family: Defines protocol group-IPv4, IPv6 etc.
Type: Defines type of a socket- stream socket, datagram socket etc.
Protocol: Set to 0 for TCP and UDP
Local Socket Address: This field defines the local socket address, a structure of type
sockaddr_in.
Remote Socket Address: This field defines the remote socket address, a structure of type
sockaddr_in.
6
Byte order transformations
u_short htons(u_short host_short)
AF_INET SOCK_DGRAM 0
SOCK_STREAM
10
“bind” System Call
bind(): Adds local socket address to an already created socket
int bind(int sockfd, const struct sockaddr *localaddr, int localaddrlen)
● Returns 0 on success, -1 on error
12
“listen” System Call
Definition and Parameters
● This system call is used by a connection-oriented server (i.e., SOCK_STREAM socket) to
indicate that it is willing to receive connections from clients.
● The function prototype is as follows – int listen(int sockfd, int backlog);
● The sockfd field is nothing but the socket descriptor obtained after executing the socket
system call.
● The backlog parameter defines the maximum length of the queue of pending connections
may grow to. This argument is usually specified as 5 which the maximum value currently
allowed.
listen(): Informs OS that the server is ready to accept connection
int listen(int sockfd, int backlog)
● Returns 0 on success, -1 on error
13
TCP three way handshake
14
accept():
accept(): called by a TCP server to remove the first connection from the corresponding
queue
int accept(int sockfd, const struct sockaddr *clientaddr, int * clientaddrelen)
18
“close” System Call
● close(): used by a process to close a socket and terminate a TCP connection
● The Unix close system call is also used to close a socket.
● The function prototype is as follows –
int close(int sockfd);
● Here fd refers to the socket descriptor.
● The close system call does not close the socket at once. Before closing it tries to send any
queued data or any queued data to be sent is flushed.
● The close system call returns 0 on success and -1 on error.
● Returns 0 on success, -1 on error
19
“sendto” System Call
● A connectionless client/server can use sendto to exchange messages between each other.
● Note that send may be used only when the socket is in a connected state. But, sendto can
be used at any time.
● The function prototype is as follows –
int sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *to,
socklen_t tolen);
● Here sockfd, buf, len and flags have the same meaning as described before in the send
system call.
● The to argument for sendto points to the protocol-specific address structure containing the
address where the data is to be sent.
● tolen is the length of the protocol-specific address structure pointed to by to.
● Both send and sendto system calls return the number of characters (in bytes) sent if the call
succeeds or else -1 is returned if an error occurred. 20
“recvfrom” System Call
● A connectionless client/server can use the recvfrom system call to receive messages as
follows –
int recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t
*fromlen);
● Here sockfd, buf, len and flags have the same meaning as in the recv system call.
● From points to the protocol-specific address structure which will be filled in with the source
address (i.e., address of the host that sent the message).
● Initially fromlen is initialized to the length of the address structure pointed to by from, on
return, fromlen is modified to indicate the actual size of the address stored.
● Like recv, recvfrom blocks until it receives a message.
● Both recv and recvfrom system calls return the number of bytes received, or -1 is returned
if an error occurred while receiving an message.
21
Socket Programming
A Simple TCP client program
#include<string.h>
#include<arpa/inet.h>
#include<iostream.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<fcntl.h>
#include<sys/stat.h>
#define MAXSIZE 50
Dept. of I&CT, MIT, Manipal 22
Contd..
main() {
int sockfd,retval;
int recedbytes,sentbytes;
struct sockaddr_in serveraddr;
char buff[MAXSIZE];
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1) {
cout<<"\nSocket creation error"; exit(0);
}
#include<iostream.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#define MAXSIZE 50
Dept. of I&CT, MIT, Manipal 26
Contd..
main()
{
int sockfd,newsockfd,retval;
socklen_t actuallen;
int recedbytes,sentbytes;
struct sockaddr_in serveraddr,clientaddr;
char buff[MAXSIZE];
int a=0;
● The creation of a new process is done using the fork() system call.
● A new program is run using the exec(l,lp,le,v,vp) family of system calls.
● These are two separate functions which may be used independently.
32
The Fork() System Call
● A call to fork() will create a completely separate sub-process which will be exactly the
same as the parent.
● The process that initiates the call to fork is called the parent process.
● The new process created by fork is called the child process.
● The child gets a copy of the parent's text and memory space.
● They do not share the same memory .
33
Fork return values
fork() system call returns an integer to both the parent and child processes:
● -1 this indicates an error with no child process created.
● A value of zero indicates that the child process code is being executed.
● Positive integers represent the child’s process identifier (PID) and the code being executed
is in the parent’s process.
34
Simple Fork Example
if ( (pid = fork()) == 0)
printf(“I am the child\n”);
else
printf(“I am the parent\n”);
35
Exec family of functions
● int execl( const char *path, const char *arg, ...);
● int execlp( const char *file, const char *arg, ...);
● int execle( const char *path, const char *arg , ..., char * const envp[]);
● int execv( const char *path, char *const argv[]);
● int execvp( const char *file, char *const argv[]);
37
Exec family of functions
The first difference in these functions is that the first four take a pathname argument while the
last two take a filename argument. When a filename argument is specified:
38
Fork() and exec()
When a program wants to have another program running in parallel, it will typically first
use fork, then the child process will use exec to actually run the desired program.
39
fork and exec function
#include <unistd.h>
pid_t fork(void);
\*The pid_t data type represents process IDs.*\
Returns: 0 in child, process ID of child in parent, -1 on error
#include <unistd.h>
int execl(const char *pathname, const char *arg(), …/*(char *) 0*/);
int execv(const char *pathname, char *const argv[]);
int execle(const char *pathname, const char *arg());
int execve(const char *pathname, char *const argv[], char *const envp[]);
int execlp(const char *filename, const char *arg());
int execvp(const char *filename, char *const argv[]);
All six return: -1 on error, no return on success 40
41
Concurrent and iterative servers
● Client A starts a transaction with the server, Client B cannot make a call until A has finished.
● Client A has already established a connection with the server, which has then created a child server process to
handle the transaction. This allows the server to process Client B’s request without waiting for A’s transaction
to complete.
42
Concurrent server
● A server can handle multiple clients at the same time in parallel, and this type of
a server is called a concurrent server
43
Client: Learning Server Address/Port
● Server typically known by name and service
E.g., “www.cnn.com” and “http”
44
Server: Allowing Clients to Wait
•Many client requests may arrive
• Server cannot handle them all at the same time
• Server could reject the requests, or let them wait
45
Server: Accepting Client Connection
● Now all the server can do is wait…
Waits for connection request to arrive
Blocking until the request arrives
And then accepting the new request
46
Client and Server: Cleaning House
● Once the connection is open
Both sides and read and write
Two unidirectional streams of data
In practice, client writes first, and server reads
… then server writes, and client reads, and so on
47
Server: One Request at a Time?
● Serializing requests is inefficient
Server can process just one request at a time
All other clients must wait until previous one is done
What makes this inefficient?
48
Concurrent Servers
● Close sock in child, newsock in parent
● Reference count for socket descriptor
Text segment
Parent
sock = socket()
/* setup socket */ while (1) { int sock;
newsock = accept(sock) int newsock;
fork() if child
read(newsock) until exit
}
Child
int sock;
int newsock;
49
Concurrent server
50
Concurrent server
● When a connection is established, accept returns, the server calls fork, and the child process
services the client (on connfd, the connected socket) and the parent process waits for
another connection (on listenfd, the listening socket).
● The parent closes the connected socket since the child handles the new client.
● The reference count is maintained in the file table entry . This is a count of the number of
descriptors that are currently open that refer to this file or socket.
● After socket returns, the file table entry associated with listenfd has a reference count of 1.
After accept returns, the file table entry associated with connfd has a reference count of 1.
● But, after fork returns, both descriptors are shared (i.e., duplicated) between the parent and
child, so the file table entries associated with both sockets now have a reference count of 2.
● Therefore, when the parent closes connfd, it just decrements the reference count from 2 to 1
and that is all. The actual cleanup and de-allocation of the socket does not happen until the
reference count reaches 0. This will occur at some time later when the child closes connfd.
51
52
Concurrent server
53
Close function
#include <unistd.h>
int close(int sockfd);
returns:0 if OK, -1 on error
54
Contd..
● The Internet Assigned Numbers Authority (IANA) maintains a list of port number
assignments.
● The port numbers are divided into three ranges:
The well-known ports: 0 through 1023. These port numbers are controlled and assigned by the IANA. When
possible, the same port is assigned to a given service for TCP, UDP, and SCTP.
For example, port 80 is assigned for a Web server, for both TCP and UDP, even though all implementations currently
use only TCP.
The registered ports: 1024 through 49151. These are not controlled by the IANA, but the IANA registers
and lists the uses of these ports as a convenience to the community. When possible, the same port is
assigned to a given service for both TCP and UDP.
For example, ports 6000 through 6063 are assigned for an X Window server for both protocols, even though all
implementations currently use only TCP. The upper limit of 49151 for these ports was introduced to allow a range for
ephemeral ports; RFC 1700 [Reynolds and Postel 1994] lists the upper range as 65535.
The dynamic or private ports, 49152 through 65535. The IANA says nothing about these ports. These are
what we call ephemeral ports. (The magic number 49152 is three-fourths of 65536.)
55
Contd..
56