You are on page 1of 39

Socket Programming in C

N.Thangaraj Asst Prof,DIST,CEG Anna University Chennai.


(Slides Adapted on Jrn Altmann s Slides)

Questions that will be Addressed


How to write a network application that sends packets between hosts (client and server) across an IP network? Answer: socket API

IP Network Client Server


2

Socket Programming Table of Contents


1. Network Application Programming Interface: 2. 3. 4. 5.
Sockets and Internet Sockets Network Programming Tips Client-Server Architecture Example: Client Programming Example: Server Programming

Layers of the IP Protocol Suite


Application Layer

e.g. ftp

Application Layer

Transport Layer

e.g. TCP, UDP

Transport Layer

Network Layer

e.g. IP

Network Layer

Link Layer

Ethernet

Link Layer
4

Protocol Suite Location


Internet Protocol Layer
Application Layer

Location
Applications (e.g. browser, game, ftp)
Application Programming Interface (API) (e.g. network API)

Transport Layer (TCP, UDP)

Operating System (e.g. Unix) Network Layer (IP)


Interface to the Network Card

Link Layer

Network Card & Device Driver (e.g. Ethernet card)


5

Network API
Operating system provides Application Programming Interface (API) for network application API is defined by a set of function types, data structures, and constants Desirable characteristics of the network interface
Simple to use  Flexible


 independent from any application  allows program to use all functionality of the network


Standardized
 allows programmer to learn once, write anywhere

Application Programming Interface for networks is called socket

Sockets
Sockets provide mechanisms to communicate between computers across a network There are different kind of sockets
DARPA Internet addresses (Internet Sockets)  Unix interprocess communication (Unix Sockets)  CCITT X.25 addresses  and many others


Berkeley sockets is the most popular Internet Socket


 

runs on Linux, FreeBSD, OS X, Windows fed by the popularity of TCP/IP


7

Internet Sockets
Support stream and datagram packets (e.g. TCP, UDP, IP) Is Similar to UNIX file I/O API (provides a file descriptor) Based on C, single thread model


does not require multiple threads

Types of Internet Sockets


Different types of sockets implement different communication types (stream vs. datagram) Type of socket: stream socket
    

connection-oriented two way communication reliable (error free), in order delivery can use the Transmission Control Protocol (TCP) e.g. telnet, ssh, http connectionless, does not maintain an open connection, each packet is independent can use the User Datagram Protocol (UDP) e.g. IP telephony

Type of socket: datagram socket




 

Other types exist: similar to the one above9

Network Programming Tips


Byte Ordering Naming Addressing

10

Byte Ordering of Integers


Different CPU architectures have different byte ordering
memory address A +1 memory address A low-order byte

Stored at little-endian computer

high-order byte

Integer representation (2 byte)

D3

F2

Stored at big-endian computer

low-order byte

high-order byte

11

Byte Ordering Problem


Question: What would happen if two computers with different integer byte ordering communicate?


Answer:

Nothing if they do not exchange integers!

wrong order of bytes, therefore, the wrong value!




But: If they exchange integers, they would get the

Example:
Message is: [Hello,512]

Message is: [Hello,1]

Message in Memory of little-endian Computer

48 45 4C 4C 6F 01 00

Message is sent across Network

Message in Memory of of big-endian Computer

48 45 4C 4C 6F 01 00
12

Byte Ordering Solution


There are two solutions if computers with different byte ordering system want to communicate


They must know the kind of architecture of the sending computer (bad solution, it has not been implemented) Introduction of a network byte order. The functions are:

uint16_t uint32_t uint16_t uint32_t

htons(uint16_t htonl(uint32_t ntohs(uint16_t ntohs(uint32_t

host16bitvalue) host32bitvalue) net16bitvalue) net32bitvalue)

Note: use for all integers (short and long), which are sent across the network


Including port numbers and IP addresses


13

Network Programming Tips


Byte Ordering Naming Addressing

14

Naming and Addressing


Host name
identifies a single host (see Domain Name System slides)  variable length string (e.g. www.berkeley.edu)  is mapped to one or more IP addresses


IP Address
written as dotted octets (e.g. 10.0.0.1)  32 bits. Not a number! But often needs to be converted to a 32-bit to use.


Port number
identifies a process on a host  16 bit number

15

Client-Server Architecture
response

Client
request

Server

Client requests service from server Server responds with sending service or error message to client
16

Simple Client-Server Example


response

Client
request

Server socket() bind() listen() accept() recv() send() recv() close()


17

socket() connect() send()

Connection establishment Data request

Data response

recv() close()

End-of-file notification

Example: Client Programming


Create stream socket (socket() ) Connect to server (connect() ) While still connected:
 

send message to server (send() ) receive (recv() ) data from server and process it

Close TCP connection and Socket (close())

18

socket(): Initializing Socket


Getting the file descriptor
int chat_sock; if ((chat_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); printf("Failed to create socket\n"); abort (); }

1.parameter specifies protocol/address family 2.parameter specifies the socket type


Other possibilities: SOCK_DGRAM

3.parameter specifies the protocol.


0 means protocol is chosen by the OS.
19

IP Address Data Structure


struct sockaddr_in { short int unsigned short int struct in_addr unsigned char }; struct in_addr { unsigned long }; sin_family; // Address family sin_port; // Port number sin_addr; // Internet address sin_zero[8];

s_addr;

// 4 bytes

Padding of sin_zeros: struct sockaddr_in has same size as struct sockaddr


20

connect(): Making TCP Connection to Server


struct sockaddr_in sin; struct hostent *host = gethostbyname (argv[1]); unsigned int server_address = *(unsigned long *) host->h_addr_list[0]; unsigned short server_port = atoi (argv[2]); memset (&sin, 0, sizeof (sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = server_address; sin.sin_port = htons (server_port); if (connect(chat_sock, (struct sockaddr *) &sin, sizeof (sin)) < 0) { perror("connect"); printf("Cannot connect to server\n"); abort(); }
21

send(): Sending Packets


int send_packets(char *buffer, int buffer_len) { sent_bytes = send(chat_sock, buffer, buffer_len, 0); if (send_bytes < 0) { perror (send"); } return 0; }

Needs socket descriptor, Buffer containing the message, and Length of the message Can also use write()
22

Receiving Packets: Separating Data in a Stream


Fixed length record
A 0 1 B 2 3 4

Fixed length record


C 5 6 7 D 8 9

receive buffer

slide through

Use records (data structures) to partition the data stream


23

Receiving Packets
int receive_packets(char *buffer, int buffer_len, int *bytes_read) { int left = buffer_len - *bytes_read; received = recv(chat_sock, buffer + *bytes_read, left, 0); if (received < 0) { buffer_len buffer perror (recv"); } if (received <= 0) { return close_connection(); } *bytes_read *bytes_read += received; while (*bytes_read > RECORD_LEN) { process_packet(buffer, RECORD_LEN); *bytes_read -= RECORD_LEN; memmove(buffer, buffer + RECORD_LEN, *bytes_read); } return 0; }

Can also use read()


24

Server Programming: Simple


Create stream socket (socket() ) Bind port to socket (bind() ) Listen for new client (listen() ) While


 

accept user connection and create a new socket (accept() ) data arrives from client (recv() ) data has to be send to client (send() )

25

bind(): Assign IP and Port


struct sockaddr_in sin; struct hostent *host = gethostbyname (argv[1]); unsigned int server_address = *(unsigned long *) host->h_addr_list[0]; unsigned short server_port = atoi (argv[2]); memset (&sin, 0, sizeof (sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = server_address; sin.sin_port = htons (server_port); if (bind(chat_sock, (struct sockaddr *) &sin, sizeof (sin)) < 0) { perror("bind"); printf("Cannot bind server application to network\n"); abort(); }

26

bind():
bind() tells the OS to assign a local IP address and local port number to the socket. Many applications let the OS choose an IP address.
Use wildcard INADDR_ANY as local address in this case.

At server, user process must call bind() to assign a port At client, bind() is not required since OS may assign available port and IP address


The server will get the port number of the client through the UDP/TCP packet header

Note: Each application is represented by a server port number 27

listen(): Wait for Connections


int listen(int sockfd, int backlog);

Puts socket in a listening state, willing to handle incoming TCP connection request. Backlog: number of TCP connections that can be queued at the socket.

28

Server Example
#include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #define MYPORT 3490 // the port users will be connecting to #define BACKLOG 10 // how many pending connections queue will hold int main(void) { int sockfd, new_fd; // listen on sockfd, new connection on new_fd struct sockaddr_in my_addr; // my address information struct sockaddr_in their_addr; // connector's address information int sin_size; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { exit(1); } perror("socket");

my_addr.sin_family = AF_INET; // host byte order my_addr.sin_port = htons(MYPORT); // short, network byte order my_addr.sin_addr.s_addr = INADDR_ANY; // auto. filled with local IP memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct 29

if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } while(1) { // main accept() loop sin_size = sizeof(struct sockaddr_in); if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) { perror("accept"); continue; } printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr)); if (send(new_fd, "Hello, world!\n", 14, 0) == -1) perror("send"); close(new_fd); } return 0; } 30

Client Example
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define PORT 3490 #define MAXDATASIZE 100 int main(int argc, char *argv[]) { int sockfd, numbytes; char buf[MAXDATASIZE]; struct hostent *he; struct sockaddr_in their_addr; // the port client will be connecting to // max number of bytes we can get // at once

// server's address information

if (argc != 2) { fprintf(stderr,"usage: client hostname\n"); exit(1); } if ((he=gethostbyname(argv[1])) == NULL) { // get the host info perror("gethostbyname"); exit(1); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); }

31

their_addr.sin_family = AF_INET; // host byte order their_addr.sin_port = htons(PORT); // short, network byte order their_addr.sin_addr = *(struct in_addr *)*he->h_addr_list; // already network byte order memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1){ perror("connect"); exit(1); } if ((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) { perror("recv"); exit(1); } buf[numbytes] = '\0'; printf("Received: %s",buf); close(sockfd); return 0; }

32

I/O Blocking
socket(); bind() ; listen();

while
accept(); recv() ; send() ;

Simple server has blocking problem


   

Suppose 5 connections accepted. Suppose next accept() blocks. Other connections cannot send and receive. Cannot get keyboard input either.
33

select() :I/O Multiplexing


waits on multiple file descriptors and timeout returns when any file descriptor


is ready to be read or  written or  indicate an error, or  timeout exceeded

advantages
simple  application does not consume CPU cycles while waiting


disadvantages


does not scale to large number of file descriptors


34

Example: Server Programming


create stream socket (socket() ) Bind port to socket (bind() ) Listen for new client (listen() ) While
Wait for (select() ) (depending on which file descriptors are ready)  accept user connection and create a new socket (accept() )  data arrives from client (recv() )  data has to be send to client (send() )

35

Server: Alternative Ways of Handling Many Clients


Forking a new process for each client: fork() But, creating new process is expensive. Multithreaded implementation: have one thread handling each client. Thread is like a process but lightweighted.
36

Network Programmer s Mistakes


byte ordering separating records in streams use of select() misinterpreting the project specification not knowing all available system calls

37

There are more System Calls


Depends on communication type


Datagram sockets use recvfrom() and sendto() for receiving and sending data

Closing connection: close(), shutdown() Convenient functions (on UNIX)


 

inet_aton, inet_ntoa inet_pton, inet_ntop

38

Compile & Run


Compile


Server
 $sand>gcc o server server.c  $rain>gcc o client client.c

Run


Server
 $sand>./server

Client
 $rain>./client sand.cise.ufl.edu

39

You might also like