You are on page 1of 40

sockets

Socket Programming in C/C++


c
Mani
Radhakrishnan and Jon Solworth
September 24, 2004

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

Contact Info

Mani Radhakrishnan
Office
4224 SEL
email
mradhakr @ cs . uic . edu
Office Hours
Tuesday 1 - 4 PM

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Introduction

Sockets are a protocol independent method of creating a


connection between processes. Sockets can be either
I

connection based or connectionless: Is a connection


established before communication or does each packet
describe the destination?

packet based or streams based: Are there message boundaries


or is it one stream?

reliable or unreliable. Can messages be lost, duplicated,


reordered, or corrupted?

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Socket characteristics

Socket are characterized by their domain, type and transport


protocol. Common domains are:
I

AF UNIX: address format is UNIX pathname

AF INET: address format is host and port number

Common types are:


virtual circuit: received in order transmitted and reliably
datagram: arbitrary order, unreliable

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Socket characteristics (contd)

Each socket type has one or more protocols. Ex:


I

TCP/IP (virtual circuits)

UDP (datagram)

Use of sockets:
I

Connectionbased sockets communicate client-server: the


server waits for a connection from the client

Connectionless sockets are peer-to-peer: each process is


symmetric.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Socket APIs
I

socket: creates a socket of a given domain, type, protocol


(buy a phone)

bind: assigns a name to the socket (get a telephone number)

listen: specifies the number of pending connections that


can be queued for a server socket. (call waiting allowance)

accept: server accepts a connection request from a client


(answer phone)

connect: client requests a connection request to a server


(call)

send, sendto: write to connection (speak)

recv, recvfrom: read from connection (listen)

shutdown: end the call


c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Connection-based communication
Server performs the following actions
I

socket: create the socket

bind: give the address of the socket on the server

listen: specifies the maximum number of connection


requests that can be pending for this process

accept: establish the connection with a specific client

send,recv: stream-based equivalents of read and write


(repeated)

shutdown: end reading or writing

close: release kernel data structures

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

TCP client

Client performs the following actions


I

socket: create the socket

connect: connect to a server

send,recv: (repeated)

shutdown

close

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

TCP-based sockets
server

client

socket

socket

bind

connect

listen

accept

close

send/recv

send/recv

shutdown

shutdown

close

close

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

socket API
#i n c l u d e <s y s / t y p e s . h>
2 #i n c l u d e <s y s / s o c k e t . h>
4

i n t s o c k e t ( i n t domain , i n t t y p e , i n t p r o t o c o l ) ;

Returns a file descriptor (called a socket ID) if successful, -1


otherwise. Note that the socket returns a socket descriptor which
is the same as a file descriptor.
The domain is AF INET.
The type argument can be:
I

SOCK STREAM: Establishes a virtual circuit for stream

SOCK DGRAM: Establishes a datagram for communication

SOCK SEQPACKET: Establishes a reliable, connection based,


two way communication with maximum message size. (This is
not available on most machines.)

protocol is usually zero, so that type defines the connection


within domain.
c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

bind
#i n c l u d e <s y s / t y p e s . h>
2 #i n c l u d e <s y s / s o c k e t . h>
4

i n t bind ( i n t sid , s t r u c t sockaddr addrPtr , i n t l e n )

Where
I

sid: is the socket id

addrPtr: is a pointer to the address family dependent


address structure

len: is the size of *addrPtr

Associates a socket id with an address to which other processes


can connect. In internet protocol the address is [ipNumber,
portNumber]

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

sockaddr
For the internet family:
struct sockaddr
sa family t
in port t
4
struct in addr
}

in {
s i n f a m i l y ; // = AF INET
sin port ;
// i s a p o r t number
sin addr ;
// an I P a d d r e s s

For unix sockets (only works between processes on the same


machine)
2
4

struct sockaddr un {
uint8 t
sun length ;
short
sun family ;
char
sun path [ 1 0 0 ] ;

//
// = AF LOCAL
// n u l l t e r m i n a t e d pathname
// ( 1 0 0 i s p o s i x 1 . g minimum )

6 }

When using internet sockets, the second parameter of bind (of


type sockaddr in *) must be cast to (sockaddr *).

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

listen

#i n c l u d e <s y s / t y p e s . h>
2 #i n c l u d e <s y s / s o c k e t . h>
4

int

l i s t e n ( int sid , int

size );

Where size it the number of pending connection requests allowed


(typically limited by Unix kernels to 5).
Returns the 0 on success, or -1 if failure.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

accept

#i n c l u d e <s y s / t y p e s . h>
2 #i n c l u d e <s y s / s o c k e t . h>
4

i n t accept ( i n t sid , s t r u c t sockaddr addrPtr , i n t l e n P t r )

Returns the socketId and address of client connecting to socket.


if lenPtr or addrPtr equal zero, no address structure is returned.
lenPtr is the maximum size of address structure that can be
called, returns the actual value.
Waits for an incoming request, and when received creates a socket
for it.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

accept styles
There are basically three styles of using accept:
Iterating server: Only one socket is opened at a time. When the
processing on that connection is completed, the
socket is closed, and next connection can be
accepted.
Forking server: After an accept, a child process is forked off to
handle the connection. Variation: the child processes
are preforked and are passed the socketId.
Concurrent single server: use select to simultaneously wait on all
open socketIds, and waking up the process only when
new data arrives.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Pro and Con of Accept styles

Iterating server is basically a low performance technique since


only one connection is open at a time.

Forking servers enable using multiple processors. But they


make sharing state difficult, unless performed with threads.
Threads, however present a very fragile programming
environment.

Concurrent single server: reduces context switches relative to


forking processes and complexity relative to threads. But does
not benefit from multiprocessors.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

send

#i n c l u d e <s y s / t y p e s . h>
2 #i n c l u d e <s y s / s o c k e t . h>
4

i n t send ( i n t sid , const char b u f f e r P t r ,


i n t len , i n t f l a g )

Send a message. Returns the number of bytes sent or -1 if failure.


(Must be a bound socket).
flag is either
I

0: default

MSG OOB: Out-of-band high priority communication

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

recv

#i n c l u d e <s y s / t y p e s . h>
2 #i n c l u d e <s y s / s o c k e t . h>
4

i n t recv ( i n t sid , char b u f f e r P t r ,


i n t len , i n t f l a g s )

Receive up to len bytes in bufferPtr. Returns the number of


bytes received or -1 on failure.
flags can be either
I

0: default

MSG OOB: out-of-bound message

MSG PEEK: look at message without removing

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

shutdown

#i n c l u d e <s y s / t y p e s . h>
2 #i n c l u d e <s y s / s o c k e t . h>
4

i n t shutdown ( i n t s i d , i n t how )

Disables sending (how=1 or how=2) or receiving (how=0 or


how=2). Returns -1 on failure.
acts as a partial close.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

connect

this is the first of the client calls


#i n c l u d e <s y s / t y p e s . h>
2 #i n c l u d e <s y s / s o c k e t . h>
4

i n t connect ( i n t sid , s t r u c t sockaddr addrPtr , i n t l e n )

Specifies the destination to form a connection with (addrPtr), and


returns a 0 if successful, -1 otherwise.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Denoting Connections

Note that a connection is denoted by a 5-tuple:


I

from IP

from port

protocol

to IP

to port

So that multiple connections can share the same IP and port.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Port usage

Note that the initiator of communications needs a fixed port to


target communications.
This means that some ports must be reserved for these well
known ports.
Port usage:
I

0-1023: These ports can only be binded to by root

1024-5000: well known ports

5001-64K-1: ephemeral ports

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

APIs for managing names and IP addresses

We next consider a number of auxiliary APIs:


I

The hostent structure: describes IP, hostname pairs

gethostbyname: hostent of a specified machine

htons, htonl, ntohs, ntohl: byte ordering

inet pton, inet ntop: conversion of IP numbers between


presentation and strings

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

gethostname

#i n c l u d e <u n i s t d . h>
2
i n t g e t h o s t n a m e ( c h a r hostname ,

s i z e t nameLength )

Returns the hostname of the machine on which this command


executes (What host am i?). Returns -1 on failure, 0 on success.
MAXHOSTNAMELEN is defined in <sys/param.h>.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

hostent structure

struct hostent {
c h a r h name ;
c h a r h a l i a s e s ;
4
int
h addrtype ;
int
h length ;
6
c h a r h a d d r l i s t
}
2

//
//
//
//
; //

o f f i c i a l ( c a n o n i c a l ) name o f t h e h o s t
n u l l t e r m i n a t e d a r r a y of a l t e r n a t i v e hostnames
h o s t a d d r e s s t y p e AF INET o r AF INET6
4 o r 16 b y t e s
IPv4 or IPv6 l i s t of a d d r e s s e s

Error is return through h error which can be:


I

HOST NOT FOUND

TRY AGAIN

NO RECOVERY

NO DATA

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Gethostbyname

Auxiliary functions
#i n c l u d e <n e t d b . h>
2
s t r u c t h o s t e n t g e t h o s t b y n a m e ( c o n s t c h a r hostname )

Translates a DNS name into a hostent.


Example:
struct hostent hostEntity =
g e t h o s t b y n a m e ( b e r t . c s . u i c . edu ) ;
memcpy ( s o c k e t A d d r>s i n a d d r ,
4
h o s t E n t i t y >h a d d r l i s t [ 0 ] ,
h o s t E n t i t y >h l e n g t h ) ;
2

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Network byte ordering

Network ordering in big endian. (Sparc is big endian, Intel is little


endian).
2

// Host t o n e t w o r k b y t e o r d e r f o r s h o r t s ( 1 6 b i t )
u i n t 1 6 t htons ( u i n t 1 6 t v ) ;

4 // Host t o n e t w o r k b y t e
uint 32t htonl ( uint 32t
6
// Network t o h o s t b y t e
8 u i n t 1 6 t ntohs ( u i n t 1 6 t

o r d e r f o r long (32 b i t )
v );
o r d e r f o r long (16 b i t )
v );

10 // Network t o h o s t b y t e o r d e r f o r l o n g ( 3 2 b i t )
uint 32t ntohl ( uint 32t v );

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

IP Number translation
IP address strings to 32 bit number
In what follows, p stands for presentation.
Hence, these routines translate between the address as a string and
the address as the number.
Hence, we have 4 representations:
I

IP number in host order

IP number in network order

Presentation (eg. dotted decimal)

Fully qualified domain name

Only the last needs an outside lookup to convert to one of the


other formats.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

inet pton

#i n c l u d e <a r p a / i n e t . h>
2
4

i n t i n e t p t o n ( i n t family , const char strPtr ,


void addrPtr ) ;

returns 1 if OK, 0 if presentation error, -1 error


Where family is either AF INET or AF INET6.
The strPtr is the IP address as a dotted string.
Finally, addrPtr points to either the 32 bit result (AF INET) or
128 bit result (AF INET6).

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

inet ntop

#i n c l u d e <a r p a / i n e t . h>
2
4

i n t i n e t n t o p ( i n t family , const char addrPtr ,


char s tr Pt r , s i z e t l e n ) ;

returns 1 if OK, 0 if presentation error, -1 error


Where family is either AF INET or AF INET6.
The strPtr is the return IP address as a dotted string.
Finally, addrPtr points to either the 32 bit (AF INET) or 128 bit
(AF INET6).
Length is the size of destination.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Example: TCP/IP Server Code


Without error checking.
sockaddr in serverAddr ;
2 s o c k a d d r &s e r v e r A d d r C a s t = ( s o c k a d d r &) s e r v e r A d d r ;
4 // g e t a t c p / i p s o c k e t
i n t l i s t e n F d = s o c k e t ( AF INET , SOCK STREAM , 0 ) ;
6
b z e r o (& s e r v e r A d d r , s i z e o f ( s e r v e r A d d r ) ) ;
8 s e r v e r A d d r . s i n f a m i l y = AF INET ;
// any i n t e r n e t i n t e r f a c e on t h i s s e r v e r .
10 s e r v e r A d d r . s i n a d d r . s a d d r = h t o n l (INADDR ANY ) ;
serverAddr . s i n p o r t = htons ( 1 3 ) ;
12
b i n d ( l i s t e n F d , &s e r v e r A d d r C a s t , s i z e o f ( s e r v e r A d d r ) ) ;
14
l i s t e n ( listenFd , 5);
16
for ( ; ; ) {
18
i n t connectFd =
a c c e p t ( l i s t e n F d , ( s o c k a d d r ) NULL , NULL ) ;
20
// . . r e a d and w r i t e o p e r a t i o n s on c o n n e c t F d . .
shutdown ( c o n n e c t F d , 2 ) ;
22
c l o s e ( connectFd ) ;
}

Note that the above is an iterative server, which means that it


serves one connection at a time.
c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Concurrent Server

To build a concurrent server:


I

a fork is performed after the accept.

The child process closes listenFd, and communicates using


connectFd.

The parent process closses connectFd, and then loops back to


the accept to wait for another connection request.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Example: TCP/IP Client code

sockaddr in serverAddr ;
2 s o c k a d d r &s e r v e r A d d r C a s t = ( s o c k a d d r &) s e r v e r A d d r ;
4 // g e t a t c p / i p s o c k e t
i n t s o c k F d = s o c k e t ( AF INET , SOCK STREAM , 0 ) ;
6
b z e r o (& s e r v e r A d d r , s i z e o f ( s e r v e r A d d r ) ) ;
8 s e r v e r A d d r . s i n f a m i l y = AF INET ;
// h o s t I P # i n d o t t e d d e c i m a l f o r m a t !
10 i n e t p t o n ( AF INET , s e r v e r N a m e , s e r v e r A d d r . s i n a d d r ) ;
serverAddr . s i n p o r t = htons ( 1 3 ) ;
12
c o n n e c t ( sockFd , s e r v e r A d d r C a s t , s i z e o f ( s e r v e r A d d r ) ) ;
14
// . . r e a d and w r i t e o p e r a t i o n s on s o c k F d . .
shutdown ( sockFd , 2 ) ;
16 c l o s e ( s o c k F d ) ;

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Connectionless communication

Communication is symmetric (peer-to-peer)


I

socket

bind: bind is optional for initiator

sendto, recvfrom (repeated)

shutdown

close

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Connectionless communication
client
socket

bind

sendto/
recvfrom
shutdown

close

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

UDP variations

It is not necessary for both sockets to bind


I

The receiver gets the address of the sender

It is possible for a UDP socket to connect


I

In this case, send/recv (or write/read) must be used instead


of sendto/recvfrom.

Asynchronous errors can be returned (using ICMP)

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

sendto

for connectionless protocols


#i n c l u d e <s y s / t y p e s . h>
2 #i n c l u d e <s y s / s o c k e t . h>
4
6

i n t sendto ( i n t sid , const void bufferPtr ,


s i z e t bufferLength , int flag ,
s t r u c t sockaddr addrPtr , s o c k l e n t addrLength )

Send a buffer, bufferPtr, of length bufferLength to address


specified by addrPtr of size addrLength. Returns number of
bytes sent or -1 on error.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

recvfrom

for connectionless protocols


#i n c l u d e <s y s / t y p e s . h>
2 #i n c l u d e <s y s / s o c k e t . h>
4

int recvfrom ( int sid , void bufferPtr , int bufferLength ,


i n t f l a g , sockaddr addrPtr , i n t addrLengthPtr )

Receive a buffer in bufferPtr of maximum length bufferLength


from an unspecified sender.
Sender address returned in addrPtr, of size *addrLengthPtr.
Returns number of bytes receive or -1 on error.

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Example: UDPserver
i n t s o c k e t I d = s o c k e t ( AF INET , SOCK DGRAM, 0 ) ;
2
4

sockaddr in serverAddr , clientAddr ;


s o c k a d d r &s e r v e r A d d r C a s t = ( s o c k a d d r &) s e r v e r A d d r ;
s o c k a d d r &c l i e n t A d d r C a s t = ( s o c k a d d r &) c l i e n t A d d r ;

6
8
10
12
14

// a l l o w c o n n e c t i o n t o any a d d r on h o s t
// f o r h o s t s w i t h m u l t i p l e n e t w o r k c o n n e c t i o n s
// and a s t s e r v e r p o r t .
s e r v e r A d d r . s i n f a m i l y = AF INET ;
serverAddr . sin port
= htons ( s e r v e r P o r t ) ;
s e r v e r A d d r . s i n a d d r . s a d d r = INADDR ANY ;
// a s s o c i a t e p r o c e s s w i t h p o r t
b i n d ( s o c k e t I d , &s e r v e r A d d r C a s t , s i z e o f ( a d d r ) ) ;

16
18
20
22

// r e c e i v e from a c l i e n t
int size = sizeof ( clientAddr );
recvfrom ( socketId , buffer , bufferSize ,
0 , c l i e n t A d d r C a s t , &s i z e ) ;

24

// r e p l y t o t h e c l i e n t j u s t r e c e i v e d from
sendto ( socketId , buffer , bufferSize ,
0 , clientAddrCast , size );

26

close ( socketId );

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

sockets

TCP
UDP

Example: UDPclient
i n t s o c k e t I d = s o c k e t ( AF INET , SOCK DGRAM, 0 ) ;
2
4

sockaddr in serverAddr , clientAddr ;


s o c k a d d r &s e r v e r A d d r C a s t = ( s o c k a d d r &) s e r v e r A d d r ;
s o c k a d d r &c l i e n t A d d r C a s t = ( s o c k a d d r &) c l i e n t A d d r ;

6
8
10
12
14
16

// s p e c i f y s e r v e r a d d r e s s , p o r t
s e r v e r A d d r . s i n f a m i l y = AF INET ;
serverAddr . sin port
= htons ( s e r v e r P o r t ) ;
s t r u c t h o s t e n t hp = g e t h o s t b y n a m e ( hostName ) ;
memcpy ( ( c h a r )& s e r v e r A d d r . s i n a d d r ,
( c h a r ) hp>h a d d r , hp>h l e n g t h ) ;
// no n e e d t o b i n d i f n o t p e e rtop e e r
int size = sizeof ( serverAddr );
sendto ( socketId , buffer , bufferSize , 0 ,
serverAddrCast , s i z e ) ;

18
20

recvfrom ( socketId , buffer , bufferSize , 0 ,


s e r v e r A d d rC a s t , &s i z e ) ;

22

close ( socketId );

c
Mani
Radhakrishnan and Jon Solworth

Socket Programming in C/C++

You might also like