0% found this document useful (0 votes)
31 views

Unit-6 Elementary TCP Sockets

The document provides an overview of elementary TCP sockets, detailing their structure, data types, and system calls used for socket programming. It explains the socket creation process, binding, listening, accepting connections, and sending/receiving data, along with examples of TCP client and server programs. Additionally, it discusses process management in Unix, including the fork and exec system calls for process creation and execution.

Uploaded by

askl263007
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
31 views

Unit-6 Elementary TCP Sockets

The document provides an overview of elementary TCP sockets, detailing their structure, data types, and system calls used for socket programming. It explains the socket creation process, binding, listening, accepting connections, and sending/receiving data, along with examples of TCP client and server programs. Additionally, it discusses process management in Unix, including the fork and exec system calls for process creation and execution.

Uploaded by

askl263007
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 55

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

Dept. of I&CT, MIT, Manipal 2


Data Types Defined
● u_char : unsigned 8 bit character

● u_short : unsigned 16 bit integer

● u_long : unsigned 32 bit integer

Dept. of I&CT, MIT, Manipal 3


Socket Address Structures
● Socket function require a pointer to a socket address structure as an argument.
● Each supported protocol suite defines its own socket address structure.
● The names of these structure begin with sockaddr_ and end with a unique suffix for each
protocol suite.

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.

Dept. of I&CT, MIT, Manipal 5


Byte ordering
● Consider a 16 bit integer that is made up of 2 bytes.
● There are two ways to store the two bytes in memory: with the lower address byte at the
starting address , known as _____________________, or with the high order byte at the
starting address, known as ________________r.
● The internet protocol use big endian byte ordering for these multi byte integers.

 Big Endian : IBM, Motorola


 Little Endian: Intel based Pcs
Network byte order is Big Endian

6
Byte order transformations
 u_short htons(u_short host_short)

 u_short ntohs(u_short network_short)

 u_long htonl(u_long host_long)

 u_long ntohl(u_long network_long)

Dept. of I&CT, MIT, Manipal 7


Socket System Calls
 socket(): Used to create a socket

int socket(int family, int type, int protocol)

AF_INET SOCK_DGRAM 0
SOCK_STREAM

Returns socket descriptor on success, -1 on error


Example
if ( (sockfd = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) {
cout<<“Socket creation error”;
exit(-1);
}

Dept. of I&CT, MIT, Manipal 8


9
Contd..

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

Why does bind is used in system call?


● Bind helps the servers to register themselves with the system. It tells the system that “any
messages received at the particular IP address and the specified port be directed to the me”.
This is required in case of both connection-oriented (like TCP) and connectionless (like
UDP) servers.
● A connectionless client needs to assure that the system assigns it some unique address, so
that the other end (the server) has a valid return address to send its responses to. This is not
required in the case of connection-oriented client as we shall see shortly.
Dept. of I&CT, MIT, Manipal 11
Contd..

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)

● Returns socket descriptor on success, -1 on error

Dept. of I&CT, MIT, Manipal 15


connect():
● connect(): Used by a process (usually a client) to establish an active connection to a remote
process (normally a server)
int connect(int sockfd, const struct sockaddr *serveraddr, int serveraddrlen)

● Returns 0 on success, -1 on error

Dept. of I&CT, MIT, Manipal 16


send():
● send(): used by a process to send data to another process running on a remote machine
● A connection-oriented client/server can use the send system call to exchange messages
between each other. The function prototype is as follows –
int send(int sockfd, const void *msg, size_t len, int flags);
● sockfd is the socket descriptor returned by the socket system call in the case of the client
and the new socket descriptor returned by the accept system call in the case of the server.
● msg is the message that has to be sent and len is the length of the message being sent.
● The flags parameter is usually set to 0.

● Returns number of bytes sent on success, -1 on error

Dept. of I&CT, MIT, Manipal 17


“recv” System Call
● recv(): used by a process to receive data from another process running on a remote machine
● To receive messages from a connected socket a client/server can use the recv system call as
follows –
int recv(int sockfd, void *buf, size_t len, int flags);
● sockfd and flags have the same meaning as in the send system call.
● Here buf is nothing but the message that will be received by the client/server.
● The len parameter specifies the number of characters (in bytes) that can be read at once.
● The recv system call blocks until a message is received.

● Returns number of bytes received on success, -1 on error

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);
}

Dept. of I&CT, MIT, Manipal 23


Contd..
serveraddr.sin_family=AF_INET;
serveraddr.sin_port=htons(3387);
serveraddr.sin_addr.s_addr=inet_addr("127.0.0.1");
\*The inet_addr() function converts the Internet host address cp from numbers-and-dots
notation into binary data in network byte order. */
retval=connect(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
if(retval==-1) {
cout<<"connection error";
exit(-1);
}

Dept. of I&CT, MIT, Manipal 24


Contd
gets(buff);
sentbytes=send(sockfd,buff,sizeof(buff),0);
if(sentbytes==-1) {
close(sockfd);
exit(0); }
recedbytes=recv(sockfd,buff,sizeof(buff),0);
puts(buff);
cout<<"\n";
close(sockfd); }

Dept. of I&CT, MIT, Manipal 25


Contd..
A simple TCP server program

#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;

Dept. of I&CT, MIT, Manipal 27


Contd..
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1) {
cout<<"\nSocket creation error";
exit(-1); }
serveraddr.sin_family=AF_INET;
serveraddr.sin_port=htons(3387);
serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);

Dept. of I&CT, MIT, Manipal 28


Contd..
retval=bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
if(retval==-1) {
cout<<"Binding error"; close(sockfd);
exit(0); }
retval=listen(sockfd,1);
if(retval==-1) { close(sockfd);
exit(0); }
actuallen=sizeof(clientaddr);

Dept. of I&CT, MIT, Manipal 29


Contd..
newsockfd=accept(sockfd,(struct sockaddr*)&clientaddr,&actuallen);
if(newsockfd==-1) {
close(sockfd);
exit(0); }
recedbytes=recv(newsockfd,buff,sizeof(buff),0);
if(recedbytes==-1) {
close(sockfd);
close(newsockfd);
exit(0); }
puts(buff);
cout<<"\n";

Dept. of I&CT, MIT, Manipal 30


Contd..
gets(buff);
sentbytes=send(newsockfd,buff,sizeof(buff),0);
if(sentbytes==-1) {
close(sockfd);
close(newsockfd);
exit(0);
}
close(newsockfd);
close(sockfd);
}

Dept. of I&CT, MIT, Manipal 31


Process Management Model
The Unix process management model is split into two distinct operations :
1. The creation of a process.
2. The running of a new program.

● 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:

• if filename contains a slash, it is taken as a pathname.


• otherwise the executable file is searched for in the directories specified by the PATH
environment variable.

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”

● Need to translate into IP address and port #


E.g., “64.236.16.20” and “80”

● Get address info with given host name and service


int getaddrinfo( char *node, char *service, struct addrinfo *hints, struct addrinfo **result)
*node: host name (e.g., “www.cnn.com”) or IP address
*service: port number or service listed in /etc/services (e.g. ftp)
hints: points to a struct addrinfo with known information

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

•Define how many connections can be pending


• int listen(int sockfd, int backlog)
• Arguments: socket descriptor and acceptable backlog
• Returns a 0 on success, and -1 on error
• Listen is non-blocking: returns immediately
What if too many clients arrive?
Some requests don’t get through
The Internet makes no promises…
And the client can always try again

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

● Accept a new connection from a client


int accept(int sockfd, struct sockaddr *addr, socketlen_t *addrlen)
Arguments: sockfd, structure that will provide client address and port, and length of the structure
Returns descriptor of socket for this new connection

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

● Closing down the connection


Either side can close the connection
… using the int close(int sockfd)

● What about the data still “in flight”


Data in flight still reaches the other end
So, server can close() before client finishes reading

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?

● May need to time share the server machine


Alternate between servicing different requests
Do a little work on one request, then switch when you are waiting for some other resource (e.g., reading file from
disk)
“Nonblocking I/O”
Or, use a different process/thread for each request
Allow OS to share the CPU(s) across processes
Or, some hybrid of these two approaches

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

You might also like