NP Unit-3

Download as pdf or txt
Download as pdf or txt
You are on page 1of 14

NETWORK PROGRAMMING

UNIT-3

ELEMENTARY TCP SOCKETS

4.1 INTRODUCTION

Figure 4.1. Socket functions for elementary TCP client/server.

• The figure shows a timeline of the typical scenario that takes place
between a TCP client and server.
• First, the server is started, then sometime later, a client is started that
connects to the server.
• We assume that the client sends a request to the server, the server
processes the request, and the server sends a reply back to the client.
• This continues until the client closes its end of the connection, which
sends an end-of-file notification to the server.
• The server then closes its end of the connection and either terminates
or waits for a new client connection.
1.SOCKET FUNCTION

To perform Network I/O, the first thing a process must do is, call the socket
function, specifying the type of communication protocol desired and protocol
family, etc.

#include <sys/socket.h>
int socket (intfamily, inttype, intprotocol);

Returns: non-negative descriptor if OK, -1 on error

• Family specifies the protocol family and is one of the constants shown
in Figure 4.2. This argument is often referred to as domain instead of
family.
• The socket type is one of the constants shown in Figure 4.3.
• The protocol argument to the socket function should be set to the
specific protocol type found in Figure 4.4, or 0 to select the system's
default for the given combination of family and type.

PARAMETERS
1.FAMILY
• family specifies the protocol family or domain
• Usually: AF_INET
• AF_LOCAL might work on CATS machines

2.Type
• type specifies type of communication.
• TCP supports only SOCK_STREAM
• UDP supports SOCK_DGRAM
3.Protocol
• protocol specifies transport protocol.
• TCP provides reliable, in-order streaming communication „ Resends lost packets,
guarantees order.
• UDP provides possibly unreliable, possibly out-of-order message delivery „
Doesn’t guarantee anything, but usually works fine

Figure 4.5. Combinations of family and type for the socket function

• Not all combinations of socket family and type are valid.


• Figure 4.5 shows the valid combinations, along with the actual protocols
that are valid for each pair. The boxes marked "Yes" are valid but do not
have handy acronyms.
• The blank boxes are not supported.
➢ The socket function returns a small non-negative integer value, similar to a file
descriptor. We call this a socket descriptor, or a sockfd.
➢ To obtain this socket descriptor, all we have specified is a protocol family (IPv4,
IPv6, or Unix) and the socket type (stream, datagram, or raw). We have not yet
specified either the local protocol address or the foreign protocol address.
AF_xxx Versus PF_xxx
▪ The "AF_" prefix stands for "address family"
▪ "PF_" prefix stands for "protocol family."
▪ The intent was that a single protocol family might support multiple address
families
▪ The PF_ value was used to create the socket
▪ The AF_ value was used in socket address structures.
▪ The <sys/socket.h> header defines the PF_ value for a given protocol to be
equal to the AF_ value for that protocol.

2.CONNECT FUNCTION
The connect function is used by a TCP client to establish a connection with a TCP
server.

#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
/* Returns: 0 if OK, -1 on error */

• sockfd is a socket descriptor returned by the socket function.


• The servaddr and addrlen arguments are a pointer to a socket address
structure (which contains the IP address and port number of the server) and
its size.
• The client does not have to call bind before calling connect: the kernel will
choose both an ephemeral port and the source IP address if necessary.
• TCP socket, the connect function initiates TCP's three-way handshake. The
function returns only when the connection is established or an error occurs.
There are several different error returns possible:

1. If the client TCP receives no response to its SYN segment, ETIMEDOUT is


returned.
2. If the server's response to the client's SYN is a reset (RST), this indicates that
no process is waiting for connections on the server host at the port specified
(the server process is probably not running).
➢ This is a hard error and the error ECONNREFUSED is returned to the client as
soon as the RST is received.
➢ An RST is a type of TCP segment that is sent by TCP when something is wrong.
Three conditions that generate an RST are:
I. When a SYN arrives for a port that has no listening server.
II. When TCP wants to abort an existing connection.
III. When TCP receives a segment for a connection that does not exist.

3. If the client's SYN elicits an ICMP "destination unreachable" from some


intermediate router, this is considered a soft error.

➢ The client kernel saves the message but keeps sending SYNs with the
same time between each SYN as in the first scenario.
➢ If no response is received after some fixed amount of time (75 seconds
for 4.4BSD), the saved ICMP error is returned to the process as
either EHOSTUNREACH or ENETUNREACH.
➢ Note that network unreachables are considered obsolete, and
applications should just treat ENETUNREACH and EHOSTUNREACH as
the same error.
Example: Nonexistent host on the local subnet *
We run the client and specify an IP address that is on the local subnet (192.168.1/24)
but the host ID (100) is nonexistent.
When the client host sends out ARP requests (asking for that host to respond with its
hardware address), it will never receive an ARP reply.

solaris % daytimetcpcli 192.168.1.100


connect error: Connection timed out

We only get the error after the connect times out.


Notice that our err_sys function prints the human-readable string associated with
the ETIMEDOUT error.
In terms of the TCP state transition diagram (Figure 2.4):

• connect moves from the CLOSED state (the state in which a socket begins
when it is created by the socket function) to the SYN_SENT state, and then,
on success, to the ESTABLISHED state.
• If connect fails, the socket is no longer usable and must be closed. We cannot
call connect again on the socket.

Each time connect fails, we must close the socket descriptor and
call socket again.
3.BIND FUNCTION
• The bind function assigns a local protocol address to a socket.
• The protocol address is the combination of either a 32-bit IPv4 address or a
128-bit IPv6 address, along with a 16-bit TCP or UDP port number.

#include <sys/socket.h>
int bind (int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
/* Returns: 0 if OK,-1 on error */

• The second argument myaddr is a pointer to a protocol-specific Address


• The third argument addrlen is the size of this address structure.

• Servers bind their well-known port when they start. (Figure 1.9) If a TCP
client or server does not do this, the kernel chooses an ephemeral port for
the socket either connect or listen is called.
• It is normal for a TCP client to let the kernel choose an ephemeral
port, unless the application requires a reserved port (Figure 2.10). But
it is rare because they are well-known port.
• Exceptions to this rule are Remote Procedure Call (RPC) servers. They
normally let the kernel choose an ephemeral port for their listening
socket since this port is then registered with the RPC port mapper.

• A process can bind a specific IP address to its socket. The IP address must
belong to an interface on the host.

• TCP client does not bind an IP address to its socket. The kernel chooses
the source IP address when the socket is connected, based on the
outgoing interface that is used.
• For a TCP server, this restricts the socket to receive incoming client
connections destined only to that IP address.

Fig 4.6 Result when specifying IP address and/or port number to bind
• If we specify a port number of 0, the kernel chooses an ephemeral port
when bind is called.
• If we specify a wildcard IP address, the kernel does not choose the local IP
address until either the socket is connected (TCP) or a datagram is sent on the
socket (UDP).

Wildcard Address and INADDR_ANY *


With IPv4, the wildcard address is specified by the constant INADDR_ANY, whose
value is normally 0. This tells the kernel to choose the IP address.

struct sockaddr_in servaddr;


servaddr.sin_addr.s_addr = htonl (INADDR_ANY); /* wildcard */

Binding a non-wildcard IP address *


A common example of a process binding a non-wildcard IP address to a socket is a
host that provides Web servers to multiple organizations:

• First, each organization has its own domain name, such as


www.organization.com.
• Next, each organization's domain name maps into a different IP address, but
typically on the same subnet.

For example, if the subnet is 198.69.10, the first organization's IP address could be
198.69.10.128, the next 198.69.10.129, and so on.
4.LISTEN FUNCTION
The listen function is called only by a TCP server and it performs two actions:

1. The listen function converts an unconnected socket into a passive socket, indicating
that the kernel should accept incoming connection requests directed to this
socket. listen moves the socket from the CLOSED state to the LISTEN state.
2. The second argument backlog to this function specifies the maximum number of
connections the kernel should queue for this socket.

This function is normally called after both the socket and bind functions and must be called
before calling the accept function.

To understand the backlog argument, we must realize that for a given


listening socket, the kernel maintains two queues:

1. An incomplete connection queue, which contains an entry for each SYN that has
arrived from a client for which the server is awaiting completion of the TCP three-
way handshake. These sockets are in the SYN_RCVD state (Figure 2.4).
2. A completed connection queue, which contains an entry for each client with whom
the TCP three-way handshake has completed. These sockets are in the ESTABLISHED
state (Figure 2.4).

These two queues are depicted in the figure below:

When an entry is created on the incomplete queue, the parameters from the listen socket are
copied over to the newly created connection. The connection creation mechanism is
completely automatic the server process is not involved.
Packet exchanges during Connection establishment *

• When a SYN arrives from a client, TCP creates a new entry on the incomplete queue
and then responds with the second segment of the three-way handshake: the
server's SYN with an ACK of the client's SYN (Section 2.6).
• This entry will remain on the incomplete queue, until:
o The third segment of the three-way handshake arrives (the client's ACK of the
server's SYN), or
o The entry times out. (Berkeley-derived implementations have a timeout of 75
seconds for these incomplete entries.)
• If the three-way handshake completes normally, the entry moves from the
incomplete queue to the end of the completed queue.
• When the process calls accept:
o The first entry on the completed queue is returned to the process, or
o If the queue is empty, the process is put to sleep until an entry is placed onto
the completed queue.

The backlog argument *


Several points to consider when handling the two queues:

• Sum of both queues.


• Berkeley-derived implementations add a fudge factor to the backlog. It is multiplied
by 1.5.
• Do not specify value of 0 for backlog, as different implementations interpret this
differently). If you do not want any clients connecting to your listening socket, close
the listening socket.
• One RTT. If the three-way handshake completes normally (no lost segments and no
retransmissions), an entry remains on the incomplete connection queue for one RTT.
• Configurable maximum value. Many current systems allow the administrator to
modify the maximum value for the backlog.
• What value should the application specify for the backlog (5 is often inadequate)
o HTTP servers now specify a larger value, but if the value specified is a
constant in the source code, to increase the constant requires recompiling the
server.
o Another method is to allow a command-line option or an environment
variable to override the default.
• Fixed number of connections. The reason for queuing a fixed number of connections
is to handle the case of the server process being busy between successive calls
to accept.
• No RST sent if queues are full. If the queues are full when a client SYN arrives, TCP
ignores the arriving SYN; it does not send an RST. This is because the condition is
considered temporary, and the client TCP will retransmit its SYN
• Data queued in the socket's receive buffer. Data that arrives after the three-way
handshake completes, but before the server calls accept, should be queued by the
server TCP, up to the size of the connected socket's receive buffer.

SYN Flooding *
SYN flooding is a type of attack (the attacker writes a program to send SYNs at a high
rate to the victim) that attempts to fill the incomplete connection queue for one or
more TCP ports.
Additionally, the source IP address of each SYN is set to a random number (called IP
spoofing) so that the server's SYN/ACK goes nowhere.
This also prevents the server from knowing the real IP address of the attacker
5.ACCEPT FUNCTION
• accept is called by a TCP server to return the next completed connection
from a client.
• Blocks if no connection is available.

#include <sys/socket.h>
int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
/* Returns: non-negative descriptor if OK, -1 on error */

• The cliaddr and addrlen arguments are used to return the protocol address of
the connected peer process (the client).
• addrlen is a value-result argument

• Before the call, we set the integer value *addrlen to the size of the socket
address structure pointed to by cliaddr;
• On return, this integer value contains the actual number of bytes stored by
the kernel in the socket address structure.

If successful, accept returns a new descriptor automatically created by the kernel. This new
descriptor refers to the TCP connection with the client.

• The listening socket is the first argument (sockfd) to accept .


• The connected socket is the return value from accept the connected socket.

Differentiate between these two sockets:

• The server creates only one listening socket, which exists for the lifetime of the server.
• The kernel creates one connected socket for each client connection that is accepted.
• When the server is finished serving a given client, the connected socket is closed.

This function returns up to three values:

• An integer return code that is either a new socket descriptor or an error indication,
• The protocol address of the client process (through the cliaddr pointer),
• The size of this address (through the addrlen pointer).

Example: Value-Result Arguments


value-result argument to accept by modifying the code to print the IP address and port of the
client:
#include "unp.h"
#include<time.h>
int
main(int argc, char **argv)
{
int listenfd, connfd;
socklen_t len;
struct sockaddr_in servaddr, cliaddr;
char buff[MAXLINE];
time_t ticks;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(13); /* daytime server */
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for ( ; ; ) {
len = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &len);
printf("connection from %s, port %d\n",
Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
ntohs(cliaddr.sin_port));
ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
Write(connfd, buff, strlen(buff));
Close(connfd);
}
}

This program does the following:

• New declarations. Two new variables are defined:


o len → value-result variable.
o cliaddr → contain the client's protocol address.
• Accept connection and print client's address.
o Initialize len to the size of the socket address structure.
o Pass a pointer to the cliaddr structure and a pointer to len as the
second and third arguments to accept.
o Call inet_ntop to convert the 32-bit IP address in the socket address
structure to a dotted-decimal ASCII string
o call ntohs to convert the 16-bit port number from network byte order
to host byte order.
5.CLOSE FUNCTION

Unix close function is used to close a socket and terminate a TCP connection.

#include <unistd.h>
int close (int sockfd);
/* Returns: 0 if OK, -1 on error */

• The default action of close with a TCP socket is to socket as closed and return
to the process immediately.
• The socket descriptor is no longer usable by the process.
• It cannot be used as an argument to read or write.
• But, TCP will try to send any data that is already queued to be sent to the
other end, and after this occurs, the normal TCP connection termination
sequence takes place.

6. getsockname and getpeername FUNCTION

• Getsockname → returns local protocol address associated with a socket.


• Getpeername → returns foreign protocol address associated with a socket.

#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);
int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);
/* Both return: 0 if OK, -1 on error */

The addrlen argument for both functions is value-result argument


Both functions socket address structure pointed to by localaddr or peeraddr.
• These two functions return the protocol address which for IPV4 and IPV6 is
the combination of an IP address and port number.
• These functions have nothing to do with domain names.
These two functions are required for the following reasons:

• After connect successfully returns in a TCP client that does not


call bind, getsockname returns the local IP address and local port number
assigned to the connection by the kernel.
• After calling bind with a port number of 0 (telling the kernel to choose the
local port number).
• getsockname returns the local port number that was assigned. It can be called
to obtain the address family of a socket.
• When a server is execed by the process that calls accept, the only way the
server can obtain the identity of the client is to call getpeername.
• For example, inetd forks and execs a TCP server (follwing figure):
o inetd calls accept, which return two values:

I. The connected socket descriptor (connfd, return value of the


function)
II. "peer's address" (an Internet socket address structure) that
contains the IP address and port number of the client.

o fork is called and a child of inetd is created, with a copy of the parent's
memory image, so the socket address structure is available to the child,
as is the connected socket descriptor.
o When the child execs the real server the memory image of the child is
replaced with the new program file for the Telnet server (the socket
address structure containing the peer's address is lost), and the
connected socket descriptor remains open across the exec.
o first function calls performed by the Telnet server is getpeername to
obtain the IP address and port number of the client.

In this example, the Telnet server must know the value of connfd There are two
common ways to do this.

1. Calling exec pass it as a command-line argument → execed program.


2. The second one is what inetd does, always setting descriptors 0, 1, and 2 to be
the connected socket.

You might also like