0% found this document useful (0 votes)
29 views15 pages

Practical 2

This document provides an overview of socket programming and the client-server model, detailing the differences between connection-oriented (TCP) and connectionless (UDP) services. It explains the types of sockets, socket API functions, and the process of sending and receiving data over sockets, along with examples and prototypes for various functions. Additionally, it covers network database administration functions and utility functions for byte ordering and error handling.

Uploaded by

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

Practical 2

This document provides an overview of socket programming and the client-server model, detailing the differences between connection-oriented (TCP) and connectionless (UDP) services. It explains the types of sockets, socket API functions, and the process of sending and receiving data over sockets, along with examples and prototypes for various functions. Additionally, it covers network database administration functions and utility functions for byte ordering and error handling.

Uploaded by

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

Practical 2

Aim: Study of Socket Programming and Client – Server model

DESCRIPTION:

 Socket

A socket is formally defined as an endpoint for communication between an application


program, and the underlying network protocols.

The two modes of services available are

 Connection-oriented service
 Connection less service

Connectionless (UDP) vs Connection-Oriented (TCP) Servers

 Programmer can choose a connection-oriented server or a connectionless server based on


their applications.
 In Internet Protocol terminology, the basic unit of data transfer is a datagram. This is
basically a header followed by some data. The datagram socket is connectionless.
 User Datagram Protocol (UDP):
1. Is a connectionless.
2. A single socket can send and receive packets from many different computers.
3. Best effort delivery.
4. Some packets may be lost some packets may arrive out of order.
 Transmission Control Protocol (TCP):
1. Is a connection-oriented.
2. A client must connect a socket to a server.
3. TCP socket provides bidirectional channel between client and server.
4. Lost data is re-transmitted.
5. Data is delivered in-order.
6. Data is delivered as a stream of bytes.
7. TCP uses flow control.
 It is simple for a single UDP server to accept data from multiple clients and reply.
 It is easier to cope with network problems using TCP.
CONNECTION-ORIENTED

Connection oriented model defines a reliable delivery service. The figure shows a
sequence of system calls for connection oriented communication. The server begins by carrying
out a passive open as follows. The socket call creates a TCP socket. The bind call then binds the
well-known port number of the server to the socket. The listen call turns the socket into a
listening socket that can accept incoming connections from clients. Finally, the accept call puts
the server process to sleep until the arrival of a client connection. The client does an active open.
The socket call creates a socket on the client side, and the connect call establishes the TCP
connection to the server with the specified destination socket address. When the TCP connection
is completed, the accept function at the server wakes up and returns the descriptor for the given
connection, namely, the source IP address, the source port number, destination IP address and
destination port number. The client and server are now ready to exchange information.

Socket system calls for connection-oriented service


 Following figure illustrates the example of client/server relationship of the socket APIs
for connection-oriented protocol (TCP).
CONNECTION-LESS

In a connection –less mode an application program sends its data immediately without
waiting for connection establishment. As a result the application program may waste its time by
sending data when the other end is not ready to accept it. Moreover, data may not arrive at the
other end if the network decides to discards it. If data arrives at the destination, it may not arrive
in the same order as it was transmitted.

The connectionless mode is often said to provide best effort service, since the network
would try its best to deliver the information but cannot guarantee the delivery.

The figure shows the sequence of system calls for a connectionless communication. No
connection is established prior to data transfer. The recvfrom call returns when a Complete UDP
data gram has been received.

Socket system calls for connection less service


 The following figure illustrates the example of client/server relationship of
the socket APIs for a connectionless protocol (UDP).

Simple Echo Client Server Using UDP:

stdin fgets Send to recvfrom


UDP UDP
Client Server

stdout fput recvfrom sendto

 Types of sockets

In general, 3 types of sockets exist on most Unix systems:

 Stream sockets
 Datagram sockets and
 Raw sockets
Stream sockets are used for stream connections, i.e. connections that exist for a long duration.
TCP connections use stream sockets.

Datagram sockets are used for short-term connections that transfer a single packet across the
network before terminating. The UDP protocol uses such sockets, due to its connection-less
nature.

Raw sockets are used to access low-level protocols directly, bypassing the higher protocols.
They are the means for a programmer to use the IP protocol, or the physical layer of the network,
directly. Raw sockets can therefor be used to implement new protocols on top of the low-level
protocols. Naturally, they are out of our scope.

Socket API functions

Create a new socket and return its descriptor.


socket()
Associate a socket with a port and address.
bind()
Establish queue for connection requests.
listen()
Accept a connection request.
accept()
Initiate a connection to a remote host.
connect()
Receive data from a socket descriptor.
recv()
Send data to a socket descriptor.
send()
Reads from files, devices, sockets etc.
read()
Writes to files, devices, sockets etc.
write()
“One-way” close of a socket descriptor.
close()
Allows you to cut off communication in a certain direction, or both ways just like
shutdown() close() does.

Socket API Functions


socket()

socket() creates an endpoint for communication and returns a file descriptor for the socket.
socket() takes three arguments:

 domain, which specifies the protocol family of the created socket. For example:
o PF_INET for network protocol IPv4 or
o PF_INET6 for IPv6.
o PF_UNIX for local socket (using a file).
 type, one of:
o SOCK_STREAM (reliable stream-oriented service or Stream Sockets)
o SOCK_DGRAM (datagram service or Datagram Sockets)
o SOCK_SEQPACKET (reliable sequenced packet service), or
o SOCK_RAW (raw protocols atop the network layer).
 protocol specifying the actual transport protocol to use. The most common are
IPPROTO_TCP, IPPROTO_SCTP, IPPROTO_UDP, IPPROTO_DCCP. These protocols
are specified in <netinet/in.h>. The value “0” may be used to select a default protocol
from the selected domain and type.

The function returns -1 if an error occurred. Otherwise, it returns an integer representing the
newly-assigned descriptor.

Prototype

int socket(int domain, int type, int protocol);


bind()

bind() assigns a socket an address. When a socket is created using socket(), it is only given a
protocol family, but not assigned an address. This association with an address must be performed
with the bind() system call before the socket can accept connections to other hosts. bind() takes
three arguments:

 sockfd, a descriptor representing the socket to perform the bind on


 my_addr, a pointer to a sockaddr structure representing the address to bind to.
 addrlen, a socklen_t field specifying the size of the sockaddr structure.

Bind() returns 0 on success and -1 if an error occurs.

Prototype

int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);

listen()

After a socket has been associated with an address, listen() prepares it for incoming connections.
However, this is only necessary for the stream-oriented (connection-oriented) data modes, i.e.,
for socket types (SOCK_STREAM, SOCK_SEQPACKET). listen() requires two arguments:

 sockfd, a valid socket descriptor.


 backlog, an integer representing the number of pending connections that can be queued
up at any one time. The operating system usually places a cap on this value. Once a
connection is accepted, it is dequeued. On success, 0 is returned. If an error occurs, -1 is
returned.

Prototype

int listen(int sockfd, int backlog);


accept()

When an application is listening for stream-oriented connections from other hosts, it is notified
of such events (cf. select() function) and must initialize the connection using the accept()
function. Accept() creates a new socket for each connection and removes the connection from
the listen queue. It takes the following arguments:

 sockfd, the descriptor of the listening socket that has the connection queued.
 cliaddr, a pointer to a sockaddr structure to receive the client's address information.
 addrlen, a pointer to a socklen_t location that specifies the size of the client address
structure passed to accept(). When accept() returns, this location indicates how many
bytes of the structure were actually used.
The accept() function returns the new socket descriptor for the accepted connection, or -1 if an
error occurs. All further communication with the remote host now occurs via this new socket.

Datagram sockets do not require processing by accept() since the receiver may immediately
respond to the request using the listening socket.

Prototype

int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);


connect()

The connect() system call connects a socket, identified by its file descriptor, to a remote host
specified by that host's address in the argument list.

Certain types of sockets are connectionless, most commonly user datagram protocol sockets. For
these sockets, connect takes on a special meaning: the default target for sending and receiving
data gets set to the given address, allowing the use of functions such as send() and recv() on
connectionless sockets.

connect() returns an integer representing the error code: 0 represents success, while -1 represents
an error.

Prototype

int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);

 Sending and receiving data over a socket

After a connection is established, there are several ways to send information over the socket.

read()

The most common way of reading data from a socket is using the read () system call, which is
defined like this:

int read(int socket, char *buffer, int buflen);

 socket - The socket from which we want to read.


 buffer - The buffer into which the system will write the data bytes.
 buflen - Size of the buffer, in bytes (actually, how much data we want to read).

The read system call returns one of the following values:

 0 - The connection was closed by the remote host.


 -1 - The read system call was interrupted, or failed for some reason.
 n - The read system call put 'n' bytes into the buffer we supplied it with.

Note that read() might read less than the number of bytes we requested, due to unavailability of
buffer space in the system.

write()

The most common way of writing data to a socket is using the write() system call, which is
defined like this:

int write(int socket, char *buffer, int buflen);

 socket - The socket into which we want to write.


 buffer - The buffer from which the system will read the data bytes.
 buflen - Size of the buffer, in bytes (actually, how much data we want to write).

The write system call returns one of the following values:

 0 - The connection was closed by the remote host.


 -1 - The write system call was interrupted, or failed for some reason.
 n - The write system call wrote 'n' bytes into the socket.

Note that the system keeps internal buffers, and the write system call write data to those buffers,
not necessarily directly to the network. Thus, a successful write() doesn't mean the data arrived at
the other end, or was even sent onto the network. Also, it could be that only some of the bytes
were written, and not the actual number we requested. It is up to us to try to send the data again
later on, when it's possible, and we'll show several methods for doing just that.
sendto() and recvfrom() for DATAGRAM (UDP)

 Since datagram sockets aren’t connected to a remote host, we need to give the destination
address before we send a packet.
 The prototype is:
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const

struct sockaddr *to, int tolen);

 This call is basically the same as the call to send() with the addition of two other pieces of
information.
 to is a pointer to a struct sockaddr (which you’ll probably have as a struct sockaddr_in
and cast it at the last minute) which contains the destination IP address and port.
 tolen can simply be set to sizeof(struct sockaddr).
 Just like with send(), sendto() returns the number of bytes actually sent (which, again,
might be less than the number of bytes you told it to send!), or -1 on error.

 Equally similar are recv() and recvfrom().

The prototype of recvfrom() is:

int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct

sockaddr *from, int *fromlen);

 Again, this is just like recv() with the addition of a couple fields.
 from is a pointer to a local struct sockaddr that will be filled with the IP address and port
of the originating machine.
 fromlen is a pointer to a local int that should be initialized to sizeof(struct sockaddr).
When the function returns, fromlen will contain the length of the address actually stored
in from. recvfrom() returns the number of bytes received, or -1 on error (with errno set
accordingly).
 Remember, if you connect() a datagram socket, you can then simply use send() and recv()
for all your transactions.
 The socket itself is still a datagram socket and the packets still use UDP, but the socket
interface will automatically add the destination and source information for you.

Socket Address

struct sockaddr_in

struct sockaddr_in {

u_char sin_len;

u_short sin_family; // Address family

u_short sin_port; // Port number

struct in_addr sin_addr; // Internet or IP address

char sin_zero[8]; // Same size as struct sockaddr

};

 The sin_family field is the address family (always AF_INET for TCP and UDP).
 The sin_port field is the port number, and the sin_addr field is the Internet address. The
sin_zero field is reserved, and you must set it to hexadecimal zeroes.
 Data type struct in_addr - this data type is used in certain contexts to contain an Internet
host address. It has just one field, named s_addr, which records the host address number
as an unsigned long int.
 sockaddr_in is a "specialized" sockaddr.
 sin_addr could be u_long.
 sin_addr is 4 bytes and 8 bytes are unused.
 sockaddr_in is used to specify an endpoint.
 The sin_port and sin_addr must be in Network Byte Order.

Network Database Administration functions

 gethostbyname() - given a hostname, returns a structure which specifies its DNS


name(s) and IP address (es).
 getservbyname() - given service name and protocol, returns a structure which specifies
its name(s) and its port address.
 gethostname() - returns hostname of local host.
 getservbyname(), getservbyport(), getservent().
 getprotobyname(), getprotobynumber(), getprotobyent(), getnetbyname(),
getnetbyaddr(), getnetent().

bzero()

The bzero function writes specified number of null bytes into specified destination

Prototype

bzero(char *dest, int nbytes);

Socket Utility Functions

Byte Ordering

The network addresses are need to formed using the network byte order. Luckily, most
networking functions accept addresses in host byte order, and return their results in network byte
order. This means only a few fields will need conversions. These will include the port numbers
only, as the addresses are already supplied by the system.

Several functions (or macros) to form 4 types of translations are:

Convert short/long from network byte order (big


ntohs()/ntohl()
endian) to host byte order.

Convert short/long from host byte order to network


htons()/htonl()
byte order.

Convert 32-bit IP address (network byte order


inet_ntoa()/inet_addr()
to/from a dotted decimal string).

perror() Print error message (based on “errno”) to stderr.


For
Print error message for gethostbyname() to stderr exam
herror()
(used with DNS). ple,
since
a port number is represented by a short integer, this could be converted from host byte order to
network byte order by doing:

short host_port = 1234;


net_port = htons(host_port);

u_long htonl(u_long host long);

u_long htons(u_short host short);

Close()

The normal LINUX close system call is also used to close a socket.
Prototype

int close(int socket);

Primary Header Files

<sys/types.h> Prerequisite typedefs.

<errno.h> Names for “errno” values (error numbers).

<sys/socket.h> struct sockaddr; system prototypes and constants.

<netdb.h.h> Network info lookup prototypes and structures.

<netinet/in.h> struct sockaddr_in; byte ordering macros.

<arpa/inet.h> Utility function prototypes.

The other functions are used in a similar way.

Address Formation

Forming addresses for Internet protocols is done using a structure named sockaddr_in, whose
definition, as given in the file /usr/include/netinet/in.h, is as follows:

struct sockaddr_in {
short int sin_family; /* Address family */
unsigned short sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */

/* Pad to size of `struct sockaddr'. */


/* Pad definition deleted */
};

The fields have the following meanings:

 sin_family: Family of protocols for this address. We will want the Internet family.
 sin_port: The port part of the address.
 sin_addr: The IP number part of the address.
 Pad: This will be explained in the next section.

Compiling A Single-Source "C" Program in UNIX systems

The command that is used to compile a C program in UNIX systems that support C compiler is
cc filename.c

(GNU compiler - gcc filename.c, Solaris system – acc filename.c)

Lets assume there is a file named 'single_main.c' that is to be compiled. This is using a command
line similar to this: cc single_main.c

Running A "C" Program in UNIX systems

The command that is used to execute the resulting program of the compiler in UNIX systems is
./ filename Eg. ./single_main

To run a recently compiled program, the command used is ./a.out

RESULT:

Thus the Socket programming and Client - Server model concepts under UNIX operating
systems has been studied successfully.

You might also like