You are on page 1of 4

Basic Socket programming

Functions prototypes and data structures

AF_INET domain

As a general rule, you will always probably need to include the following header files:

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h> // for name resolution

Basic data structures: sockaddr and sockaddr_in

struct sockaddr {
unsigned short sa_family; // Address family, AF_xxx
char sa_data[14]; // 14 octets
};

sa_data contains the socket parameters. In practice, we use the struct sockaddr_in which provides easy access to the fields.
Pointers towards sockaddr and sockaddr_in can always be swapped (or casted).

struct sockaddr_in {
short int sin_family; // AF_INET
unsigned short int sin_port; // Port number
struct in_addr sin_addr; // IP address
unsigned char sin_zero[8]; // 8 null char
};

struct in_addr {
unsigned long s_addr; // 4 octets for IP address (IPv4)
};

Note:

The fields sin_port and sin_addr must be in "Network Byte Order". You thus have to use the functions htons, htonl,
ntohs, and ntohl to do the appropriate conversions.

Some useful functions to convert IP addresses from/to dotted decimal format:

in_addr_t inet_addr( const char *cp);

Converts the string cp given in "a.b.c.d" format into a unsigned long integer (value returned by the function).

int inet_aton( const char *cp, struct in_addr in);

Converts the string cp given in "a.b.c.d" format into the in unsigned long integer

char * inet_ntoa( struct in_addr in);

Converts the in unsigned long integer into a "a.b.c.d" string format.

Universität Basel, CS221- Computer Networks and Security – Christophe Jelger - 2005 Page 1
Example:

struct sockaddr_in my_socket;

my_socket.sin_family = AF_INET;
my_socket.sin_port = htons(80); // conversion host -> network (80 is the port for HTTP)
my_socket.sin_addr.s_addr = inet_addr("130.79.44.193"); // or inet_aton( "130.79.44.193", &(my_socket.sin_addr) );
memset( &(my_socket.sin_zero), '\0', 8); // set to zero

printf("%s", inet_ntoa(my_socket.sin_addr) ); // display IP address in dotted decimal format (a.b.c.d)

Name resolution

Name resolution functions permits to retrieve the IP address associated with a name (e.g. 217.12.3.11 for
www.yahoo.ch).

struct hostent {
char *h_name; // main name
char **h_aliases; // alternative names (aliases)
int h_addrtype; // address type (usually AF_INET)
int h_length; // length of address (in octets)
char **h_addr_list; // alternate addresses (in Network Byte Order)
};
#define h_addr h_addr_list[0] // fist address of h_addr_list

struct hostent * gethostbyname( char *name);

This function permits to obtain the IP address(es) associated with a given name.

int getpeername(int sockfd, struct sockaddr *addr, int *addrlen);

Allows to obtain information related to the socket sockfd.

Example:

struct hostent *info_yahoo;


int i = 0;

info_yahoo = gethostbyname( "www.yahoo.ch" );

printf("The IP address of %s is %s", info_yahoo->h_name, inet_ntoa( * ((struct in_addr *)info_yahoo->h_addr )));

/* aliases */

while( *(pc_ip->h_aliases + i) != NULL )


{
printf("\n\tAlias: %s", *(pc_ip->h_aliases + i) );
i++;
}

Universität Basel, CS221- Computer Networks and Security – Christophe Jelger - 2005 Page 2
Socket creation and connection management

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

Socket creation: domain = AF_INET, type = SOCK_STREAM (TCP) or SOCK_DGRAM (UDP), protocol = 0.

In all the prototypes given below, sockfd is a socket descriptor obtained via the socket() call.

int close( int sockfd ); Closes socket

int bind( int sockfd, struct sockaddr *sock_info, int addrlen);

Bind the socket to a certain port and IP address. If sock_info.sin_port = htons(0), the system will assign to the
socket a free port. If sock_info.sin_addr.s_addr = INADDR_ANY, the system will assign to the socket an IP
address of the machine.

int listen( int sockfd, int max_number);

The socket sockfd is set in a state where it waits for incoming connections. The integer max_number specifies
the maximum size of the queue of connections waiting to be accept()ed.

int accept( int sockfd, struct sockaddr *sock_info, int addrlen);

An incoming connection must be accept()ed. sockfd is the socket descriptor used in the listen() call, and
sock_info will contain the information related to the incoming connection.
CAREFUL: accept() returns a new socket descriptor that is used to send/receive data. The original socket
continues to be used only to detect new incoming connections.

int connect( int sockfd, struct sockaddr *sock_info, int addrlen);

Connects a socket to the destination specified in sock_info.

Example:

int sockfd, new_fd; // listen() on sock_fd, send/receive on new_fd


struct sockaddr_in my_addr; // my machine
struct sockaddr_in their_addr; // the correspondent
int sin_size;

sockfd = socket(AF_INET, SOCK_STREAM, 0);

my_addr.sin_family = AF_INET; // host byte order


my_addr.sin_port = htons(80); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // my IP address
memset(&(my_addr.sin_zero), '\0', 8); // set to zero

bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));

listen(sockfd, 5); // set socket in listening state, max queue length is 5

sin_size = sizeof(struct sockaddr_in);


new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); // then use new_fd to send/receive data

.
Universität Basel, CS221- Computer Networks and Security – Christophe Jelger - 2005 Page 3
Sending/receiving data: blocking calls !

int send( int sockfd, const void *msg, int length, int flags);

Send length octets of the data stored at msg on the socket sockfd of type SOCK_STREAM.

int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);

Same as send() but with a SOCK_DGRAM socket. The struct pointed by to contains the IP address and the
UDP port of the destination.

int recv( int sockfd, void *buffer, int length, unsigned int flags);

Wait for a maximum of length octets of data on the SOCK_STREAM socket sockfd – write data to buffer.

int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);

Same as recv() but with a SOCK_DGRAM socket. The struct pointed by from will contain the IP address and
the UDP port of the sender.

Some details about the integer flags. It can take the following values, or 0 for default behavior.

For send and sendto: MSG_OOB /* process out-of-band data */


MSG_PEEK /* peek at incoming message */
MSG_DONTROUTE /* bypass routing, use direct interface */
MSG_EOR /* data completes record */
MSG_EOF /* data completes transaction */

For recv and recvfrom: MSG_OOB /* process out-of-band data */


MSG_PEEK /* peek at incoming message */
MSG_WAITALL /* wait for full request or error */

int shutdown( int sockfd, int how );

Restrain the use of the socket sockfd according to the value of how: 0 = reception not allowed, 1 = emission not allowed,
2 = reception and emission not allowed. WARNING: shutdown() does not close a socket!

Sockets (descriptors) monitoring

int select( int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

Note: the following header files must be included <sys/time.h> and <unistd.h>

select() monitors a set of descriptors to detect if write or read operations have been performed or must be performed.
The following MACROs are used to manipulate the sets of descriptors.

FD_ZERO(fd_set *set) Initialize the set


FD_SET(int fd, fd_set *set) Add descriptor fd to the set
FD_CLR(int fd, fd_set *set) Remove descriptor fd from the set
FD_ISSET(int fd, fd_set *set) Check if descriptor fd belongs to the set

We remind you that all the functions descriptions are available on Unix systems via the man pages.
Source: Beej's guide to network programming (http://www.ecst.csuchico.edu/~beej/guide/net/).
Book: R. Stevens, B. Fenner, and A. Rudoff, UNIX Network Programming, Vol. 1, 3rd edition, Addison-Wesley.
Universität Basel, CS221- Computer Networks and Security – Christophe Jelger - 2005 Page 4

You might also like