Chapter 19
Custom Applications with Sockets

 19.1 Prerequisites
  19.1.1 Assumed Knowledge
  19.1.2 Linux and Network Setup
 19.2 Programming with Sockets
  19.2.1 Servers Handling Multiple Connections
  19.2.2 Further Explanation
 19.3 TCP Sockets in C
  19.3.1 Example Usage
  19.3.2 TCP Client
  19.3.3 TCP Server
 19.4 UDP Sockets in C
  19.4.1 Example Usage
  19.4.2 UDP Client
  19.4.3 UDP Server
 19.5 TCP Sockets in Python
  19.5.1 Example Usage
  19.5.2 TCP Client
  19.5.3 TCP Server
 19.6 UDP Sockets in Python
  19.6.1 Example Usage
  19.6.2 UDP Client
  19.6.3 UDP Server
 19.7 Raw Sockets in Python

File: nsl/sockets.tex, r1669

Many Internet applications use a client/server model for communication: a server listens for connections; and a client initiates connections to the server. How are these client and server programs implemented? In this chapter you will learn the basic programming constructs, called sockets, to create a client and server program. You can use these programming constructs to implement your own client/server application. This chapter first explains sockets using the C programming language as an example. Sections 19.3 to 19.4 provide detailed examples of socket application in C. Then Sections 19.5 to 19.7 provide examples using Python programming language. All the source code is available for download via https://sandilands.info/nsl/source/.

19.1 Prerequisites

19.1.1 Assumed Knowledge

This chapter assumes you have knowledge of:

Basic Linux command line skills, as covered in Chapter 4, are assumed. You will need to be able to:

19.1.2 Linux and Network Setup

All of the practical tasks in this chapter can be completed on a single Linux computer, however it is preferable to use two computers (client and server).

The recommended virtnet topology is:

19.2 Programming with Sockets

Sockets are programming constructs used to communicate between processes. There are different types of systems that sockets can be used for, the main one of interest to us are Internet-based sockets (the other commonly used socket is Unix sockets).

Sockets for Internet programming were created in early versions of Unix (written in C code). Due to the popularity of Unix for network computing at the time, these Unix/C based sockets become quite common. Now, the same concept has been extended to other languages and other operating systems. So although we use C code and a Unix-based system (Ubuntu Linux), the principles can be applied to almost any computer system.

There are two main Internet socket types, corresponding to the two main Internet transport protocols:

  1. Stream sockets use TCP to communicate. TCP is stream-oriented, sending a stream of bytes to the receiver. It is also a reliable transport protocol, which means it guarantees that all data arrives at the receiver, and arrives in order. TCP starts be setting up a connection (we have seen the 3-way handshake in other labs), and then sending data between sender and receiver. TCP is used for most data-oriented applications like web browsing, file transfer and email.
  2. Datagram sockets use UDP to communicate. UDP is an unreliable protocol. There is no connection setup or retransmissions. The sender simply sends a packet (datagram) to the receiver, and hopes that it arrives. UDP is used for most real-time oriented applications like voice over IP and video conversations.

Here we will focus on stream sockets, but examples of datagram sockets are given in later sections.

The basic procedure is shown in Figure 19.1. The server must first create a socket, then associate or bind an IP address and port number to that socket. Then the server listens for connections.


PIC

Figure 19.1: Socket communications

The client creates a socket and then connects to the server. The connect() system call from the client triggers a TCP SYN segment from client to server.

The server accepts the connection from the client. The accept() system call is actually a blocking function—when the program calls accept(), the server does not return from the function until it receives a TCP SYN segment from a client, and completes the 3-way handshake.

After the client returns from the connect() system call, and the server returns from the accept() system call, a connection has been established. Now the two can send data.

Sending and receiving data is performed using the write() and read() functions. read() is a blocking function—it will only return when the socket receives data. You (the application programmer) must correctly coordinate reads and writes between the client and server. If a client calls the read() function, but no data is sent from the server, then the client will wait forever!

19.2.1 Servers Handling Multiple Connections

It is common for a server to be implemented such that it can handle multiple connections at a time. The most common way to do this is for a main server process to listen for connections, and when a connection is established, to create a child process to handle that connection (while the parent process returns to listening for connections). In our example, we use the fork() system call.

The fork() system call creates a new process, which is the child process of the current process. Both the parent and child process execute the next command following the call to fork(). fork() returns a process ID, which may be:

Hence we can use the process ID returned from fork() to determine what to do next—the parent process (pid > 0) will end the current loop and go back to waiting for connections. The child process (pid = 0) will perform the data exchange with the client.

19.2.2 Further Explanation

The next sections provide examples of programming with sockets in both C and Python programming languages. You should read the source code for the corresponding client and server, run the code, and then try to understand the output produced.

For the C programming language, most of the socket system calls are described in detail in their individual man pages. You should use the man pages for finding out further details of each function. Note that you may have to specify the section of man pages to use (which is section 2, the System Calls section):

$ man -S2 accept
ACCEPT(2)                  Linux Programmer's Manual                 ACCEPT(2)

NAME
        accept - accept a connection on a socket
...

19.3 TCP Sockets in C

Now we present example implementations of clients and servers that can exchange data across the Internet. They are implemented in C. There is a TCP version and a UDP version. The source code is quite old (there are newer, better constructs available), and may produce warnings when compiled, however it still executes as intended. The purpose of this code is to show a simple example of using sockets in C to create an Internet client/server application. If you want to create your own application, it is recommended you look for other (better) ways to implement in C.

19.3.1 Example Usage

On one computer compile the server and then start it. The server takes a port number as a command line argument:

$ gcc -o tcpserver socket_tcp_server.c
$ ./tcpserver 5001

On another computer compile the client and then start it. The client takes the IP address of the server and the port number it uses as command line arguments:

$ gcc -o tcpclient socket_tcp_client.c
$ ./tcpclient 127.0.0.1 5001

The client prompts for a message. Type in a message and press Enter. The result should be the message being displayed at the server and then the client printing “I got your message”. The client exits, but the server keeps running (other clients can connect).

An example on the client:

$ ./tcpclient 127.0.0.1 5001
Please enter the message: Hello from Steve
I got your message
$

And on the server:

$ ./tcpserver 5001
Here is the message: Hello from Steve

19.3.2 TCP Client

 
1/* ***************************************************************** 
2* ITS 332 Information Technology II (Networking) Lab 
3* Semester 2, 2010 
4* SIIT 
5* 
6* Client/Server Programming Lab 
7* File: client.c 
8* Date: 24 Jan 2007 
9* Version: 1.0 
10* 
11* Description: 
12* Client to demonstrate TCP sockets programming. You should read the 
13* server.c code as well. 
14* 
15* Usage: 
16* client server_ip_address server_port_number 
17* 
18* Acknowledgement: 
19* This code is based on the examples and descriptions from the 
20* Computer Science Department, Rensselaer Polytechnic Institute at: 
21* http://www.cs.rpi.edu/courses/sysprog/sockets/sock.html 
22* 
23* ***************************************************************** */ 
24 
25#include <stdio.h> 
26#include <string.h> 
27#include <stdlib.h> 
28#include <sys/types.h> 
29#include <sys/socket.h> 
30#include <netinet/in.h> 
31#include <netdb.h> 
32 
33/* ================================================================= */ 
34/* error: display an error message and exit                */ 
35/* ================================================================= */ 
36void error(char *msg) 
37{ 
38   perror(msg); 
39   exit(0); 
40} 
41 
42/* ================================================================= */ 
43/* main: connect to server, prompt for a message, send the message, */ 
44/* receive the ack from server and then exit               */ 
45/* ================================================================= */ 
46int main(int argc, char *argv[]) 
47{ 
48   /* socket file descriptor, port number of server, and number of bytes */ 
49   int sockfd, portno, n; 
50   struct sockaddr_in serv_addr; /* server address */ 
51   /* The hostent structure defines a host computer on the Internet. It 
52     contains field which describe the host name, aliases for the name, 
53     address type and actual address (e.g. IP address) */ 
54   struct hostent *server; 
55   char buffer[256]; 
56 
57   /* The user must enter two parameters on the command line: 
58      - server host name or IP address 
59      - port number used by server */ 
60   if (argc < 3) { 
61     fprintf(stderr,"usage%shostnameport\n", argv[0]); 
62     exit(0); 
63   } 
64   /* Get the port number for server entered by user */ 
65   portno = atoi(argv[2]); 
66 
67   /* Create an Internet stream (TCP) socket */ 
68   sockfd = socket(AF_INET, SOCK_STREAM, 0); 
69   if (sockfd < 0) 
70      error("ERRORopeningsocket"); 
71 
72   /* The gethostbyname() system call uses DNS to determine the IP 
73     address of the host */ 
74   server = gethostbyname(argv[1]); 
75   if (server == NULL) { 
76      fprintf(stderr,"ERROR,nosuchhost\n"); 
77      exit(0); 
78   } 
79 
80   /* Set the server address to all zeros */ 
81   bzero((char *) &serv_addr, sizeof(serv_addr)); 
82   serv_addr.sin_family = AF_INET; /* Internet family of protocols */ 
83 
84   /* Copy server address obtained from gethostbyname to our 
85     serv_addr structure */ 
86   bcopy((char *)server->h_addr, 
87      (char *)&serv_addr.sin_addr.s_addr, 
88      server->h_length); 
89 
90   /* Convert port number to network byte order */ 
91   serv_addr.sin_port = htons(portno); 
92 
93   /* The connect() system call establishes a connection to the server. The 
94     three parameters are: 
95      - socket file descriptor 
96      - address of server 
97      - size of the servers address */ 
98   if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
99      error("ERRORconnecting"); 
100 
101   /* Once connected, the client prompts for a message, and the users 
102     input message is obtained with fgets() and written to the socket 
103     using write(). */ 
104   printf("Pleaseenterthemessage:"); 
105   bzero(buffer,256); 
106   fgets(buffer,255,stdin); 
107   n = write(sockfd,buffer,strlen(buffer)); 
108   if (n < 0) 
109      error("ERRORwritingtosocket"); 
110 
111   /* Zero a buffer and then read from the socket */ 
112   bzero(buffer,256); 
113   n = read(sockfd,buffer,255); 
114   if (n < 0) 
115      error("ERRORreadingfromsocket"); 
116 
117   /* Display the received message and then quit the program */ 
118   printf("%s\n",buffer); 
119   return 0; 
120}

19.3.3 TCP Server

 
1/* ***************************************************************** 
2* ITS 332 Information Technology II (Networking) Lab 
3* Semester 2, 2010 
4* SIIT 
5* 
6* Client/Server Programming Lab 
7* File: server.c 
8* Date: 24 Jan 2007 
9* Version: 1.0 
10* 
11* Description: 
12* Server to demonstrate TCP sockets programming 
13* 
14* Usage: 
15* server server_port_number 
16* 
17* Acknowledgement: 
18* This code is based on the examples and descriptions from the 
19* Computer Science Department, Rensselaer Polytechnic Institute at: 
20* http://www.cs.rpi.edu/courses/sysprog/sockets/sock.html 
21* 
22* ***************************************************************** */ 
23 
24#include <stdio.h> 
25#include <string.h> 
26#include <stdlib.h> 
27#include <sys/types.h> 
28#include <sys/socket.h> 
29#include <netinet/in.h> 
30 
31/* ================================================================= */ 
32/* Function Prototypes                                 */ 
33/* ================================================================= */ 
34void dostuff(int); 
35 
36/* ================================================================= */ 
37/* error: display an error message and exit                */ 
38/* ================================================================= */ 
39void error(char *msg) 
40{ 
41   perror(msg); 
42   exit(1); 
43} 
44 
45/* ================================================================= */ 
46/* main: listen for connections, and create new process for each */ 
47/* connection. Receive the message from client and acknowledge. */ 
48/* ================================================================= */ 
49int main(int argc, char *argv[]) 
50{ 
51   /* file descriptors that contain values return from socket and 
52   and accept system calls */ 
53   int sockfd, newsockfd; 
54   int portno; /* port number on which server accepts connections */ 
55   int pid; /* process ID for newly created child process */ 
56   /* sockaddr_in is a structure containing an IP address - it is 
57      defined in netinet/in.h */ 
58   struct sockaddr_in serv_addr, cli_addr; 
59   size_t clilen; /* size of the address of the client */ 
60 
61   /* The user must pass the port number that the server listens on 
62      as a command line parameter (otherwise error) */ 
63   if (argc < 2) { 
64      fprintf(stderr,"ERROR,noportprovided\n"); 
65      exit(1); 
66   } 
67 
68   /* First we must create a socket using the socket() system call. 
69      The three parameters are: 
70      - address domain of the socket. It may be an Unix socket, an 
71        Internet socket or others. We use the Internet socket which 
72        is defined by the constant AF_INET 
73      - socket type. Stream (TCP), or Datagram (UDP, SOCK_DGRAM) or 
74        a raw socket (for accessing IP directly). 
75      - the protocol. 0 means the operating system will choose the 
76        most appropriate protocol: TCP for stream and UDP for 
77        datagram. 
78      The call to socket returns a file descriptor (or -1 if it fails) */ 
79   sockfd = socket(AF_INET, SOCK_STREAM, 0); 
80   if (sockfd < 0) 
81      error("ERRORopeningsocket"); 
82 
83   /* bzero sets all values in a buffer to 0. Here we set the server 
84      address to 0 */ 
85   bzero((char *) &serv_addr, sizeof(serv_addr)); 
86 
87   /* Get the port number that the user entered via command line */ 
88   portno = atoi(argv[1]); 
89 
90   /* Now we set the server address in the structure serv_addr */ 
91   /* Note that INADDR_ANY is a constant that refers to the IP 
92      address of the machine the server is running on. */ 
93   /* Note that the port number must be specified in network byte order. 
94      Different computer systems represents bytes in different order: 
95      big endian - most significant bit of byte is first 
96      little endian - least significant bit of byte is first 
97      For this reason, everything must be converted to network byte 
98      order (which is big endian). htons does this conversion. */ 
99   serv_addr.sin_family = AF_INET; /* Protocol family: Internet */ 
100   serv_addr.sin_addr.s_addr = INADDR_ANY; /* Server address */ 
101   serv_addr.sin_port = htons(portno); /* Port number */ 
102 
103   /* The bind() system call binds a socket to an address. This 
104      may fail if for example the port number is already being 
105      used on this machine. */ 
106   if (bind(sockfd, (struct sockaddr *) &serv_addr, 
107          sizeof(serv_addr)) < 0) 
108          error("ERRORonbinding"); 
109 
110   /* The listen() system call tells the process to listen on the 
111      socket for connections. The first parameter is a file descriptor 
112      for the socket and the second parameter is the number of 
113      connections that can be queued while the process is handling this 
114      connection. 5 is a reasonable value for most systems */ 
115   listen(sockfd,5); 
116   clilen = sizeof(cli_addr); 
117 
118   /* Now we enter an infinite loop, waiting for connections from clients. 
119      When a connection is established, we will create a new child process 
120      using fork(). The child process will handle the data transfer with 
121      the client. The parent process will wait for another connection. */ 
122   while (1) { 
123   /* The accept() system call causes the process to block until a 
124         client connects with the server. The process will wake up once 
125         the connection has been established (e.g. TCP handshake). 
126         The parameters to accept are: 
127         - the file descriptor of the socket we are waiting on 
128         - a structure to store the address of the client that connects 
129         - a variable to store the length of the client address 
130         It returns a new file descriptor for the socket, and all 
131         communication is now done with this new descriptor. */ 
132      newsockfd = accept(sockfd, 
133           (struct sockaddr *) &cli_addr, &clilen); 
134      if (newsockfd < 0) 
135         error("ERRORonaccept"); 
136 
137   /* Create child process to handle the data transfer */ 
138      pid = fork(); 
139      if (pid < 0) 
140         error("ERRORonfork"); 
141      /* The process ID in the child process will be 0. Hence the child 
142         process will close the old socket file descriptor and then call 
143         dostuff() to perform the interactions with the client. When 
144         complete, the child process will exit. */ 
145      if (pid == 0) { 
146         close(sockfd); 
147         dostuff(newsockfd); 
148         exit(0); 
149      } 
150   /* This is called by the parent process only. It closes the 
151         new socket file descriptor, which is not needed by the parent */ 
152      else close(newsockfd); 
153   } /* end of while */ 
154   return 0; /* we never get here because we are in infinite loop */ 
155} 
156 
157/* ================================================================= */ 
158/* dostuff: exchange some messages between client and server. There */ 
159/* is a separate instance of this function for each connection. */ 
160/* ================================================================= */ 
161void dostuff (int sock) 
162{ 
163  int n; 
164  char buffer[256]; 
165 
166  /* Set a 256 byte buffer to all zeros */ 
167  bzero(buffer,256); 
168 
169  /* Read from the socket. This will block until there is something for 
170    it to read in the socket (i.e. after the client has executed a 
171    write()). It will read either the total number of characters in the 
172    socket or 255, whichever is less, and return the number of characters 
173    read. */ 
174  n = read(sock,buffer,255); 
175  if (n < 0) error("ERRORreadingfromsocket"); 
176 
177  /* Display the message that was received */ 
178  printf("Hereisthemessage:%s\n",buffer); 
179 
180  /* Write a message to the socket. The third parameter is the size of 
181    the message */ 
182  n = write(sock,"Igotyourmessage",18); 
183  if (n < 0) error("ERRORwritingtosocket"); 
184}

19.4 UDP Sockets in C

19.4.1 Example Usage

On one computer compile the server and then start it. The server takes a port number as a command line argument:

$ gcc -o udpserver socket_udp_server.c
$ ./udpserver 5001

On another computer compile the client and then start it. The client takes the IP address of the server and the port number it uses as command line arguments:

$ gcc -o udpclient socket_udp_client.c
$ ./udpclient 127.0.0.1 5001

The client prompts for a message. Type in a message and press Enter. The result should be the message being displayed at the server and then the client printing “Got your message”. The client exits, but the server keeps running (other clients can connect).

An example on the client:

$ ./udpclient 127.0.0.1 5002
Please enter the message: a udp test
Got an ack: Got your message
$

And on the server:

$ ./udpserver 5002
Received a datagram: a udp test

19.4.2 UDP Client

 
1/* ***************************************************************** 
2* ITS 332 Information Technology II (Networking) Lab 
3* Semester 2, 2006 
4* SIIT 
5* 
6* Client/Server Programming Lab 
7* File: client_idp.c 
8* Date: 29 Jan 2007 
9* Version: 1.0 
10* 
11* Description: 
12* Client to demonstrate UDP sockets programming. You should read the 
13* server_udp.c code as well. 
14* 
15* Usage: 
16* client server_ip_address server_port_number 
17* 
18* Acknowledgement: 
19* This code is based on the examples and descriptions from the 
20* Computer Science Department, Rensselaer Polytechnic Institute at: 
21* http://www.cs.rpi.edu/courses/sysprog/sockets/sock.html 
22* 
23* ***************************************************************** */ 
24 
25#include <stdio.h> 
26#include <string.h> 
27#include <stdlib.h> 
28#include <sys/types.h> 
29#include <sys/socket.h> 
30#include <netinet/in.h> 
31#include <arpa/inet.h> 
32#include <netdb.h> 
33 
34/* ================================================================= */ 
35/* error: display an error message and exit                */ 
36/* ================================================================= */ 
37void error(char *msg) 
38{ 
39   perror(msg); 
40   exit(0); 
41} 
42 
43/* ================================================================= */ 
44/* main: create socket and send message to server           */ 
45/* ================================================================= */ 
46int main(int argc, char *argv[]) 
47{ 
48  int sock, n; 
49  struct sockaddr_in server, from; 
50  struct hostent *hp; 
51  char buffer[256]; 
52  size_t length; 
53 
54  /* User must input server and port number */ 
55  if (argc != 3) { printf("Usage:serverport\n"); 
56               exit(1); 
57  } 
58 
59  /* Create a Datagram (UDP) socket */ 
60  sock= socket(AF_INET, SOCK_DGRAM, 0); 
61  if (sock < 0) error("socket"); 
62 
63  server.sin_family = AF_INET; 
64 
65  /* Get the IP address for destination server */ 
66  hp = gethostbyname(argv[1]); 
67  if (hp==0) error("Unknownhost"); 
68 
69  /* Set the server address and port */ 
70  bcopy((char *)hp->h_addr, 
71      (char *)&server.sin_addr, 
72      hp->h_length); 
73  server.sin_port = htons(atoi(argv[2])); 
74 
75  length=sizeof(struct sockaddr_in); 
76 
77  /* Prompt for message from user */ 
78  printf("Pleaseenterthemessage:"); 
79  bzero(buffer,256); 
80  fgets(buffer,255,stdin); 
81 
82  /* Send message to socket (server) */ 
83  n=sendto(sock,buffer, 
84         strlen(buffer),0,(struct sockaddr *) &server,length); 
85  if (n < 0) error("Sendto"); 
86 
87  /* Receive response from server */ 
88  n = recvfrom(sock,buffer,256,0,(struct sockaddr *) &from, &length); 
89  if (n < 0) error("recvfrom"); 
90 
91  /* Display response to user */ 
92  write(1,"Gotanack:",12); 
93  write(1,buffer,n); 
94}

19.4.3 UDP Server

 
1/* ***************************************************************** 
2* ITS 332 Information Technology II (Networking) Lab 
3* Semester 2, 2006 
4* SIIT 
5* 
6* Client/Server Programming Lab 
7* File: server_udp.c 
8* Date: 29 Jan 2007 
9* Version: 1.0 
10* 
11* Description: 
12* Server to demonstrate UDP sockets programming 
13* 
14* Usage: 
15* server server_port_number 
16* 
17* Acknowledgement: 
18* This code is based on the examples and descriptions from the 
19* Computer Science Department, Rensselaer Polytechnic Institute at: 
20* http://www.cs.rpi.edu/courses/sysprog/sockets/sock.html 
21* 
22* ***************************************************************** */ 
23 
24#include <stdio.h> 
25#include <string.h> 
26#include <stdlib.h> 
27#include <sys/types.h> 
28#include <sys/socket.h> 
29#include <netinet/in.h> 
30#include <netdb.h> 
31 
32/* ================================================================= */ 
33/* error: display an error message and exit                */ 
34/* ================================================================= */ 
35void error(char *msg) 
36{ 
37   perror(msg); 
38   exit(0); 
39} 
40 
41/* ================================================================= */ 
42/* main: create socket and receive/send to socket           */ 
43/* ================================================================= */ 
44int main(int argc, char *argv[]) 
45{ 
46  int sock, length, n; 
47  struct sockaddr_in server; /* server address structure */ 
48  struct sockaddr_in from; /* source address structure */ 
49  char buf[1024]; 
50  size_t fromlen; 
51 
52  /* Port number must be passed as parameter */ 
53  if (argc < 2) { 
54    fprintf(stderr, "ERROR,noportprovided\n"); 
55    exit(0); 
56  } 
57 
58  /* Create a Datagram (UDP) socket */ 
59  sock=socket(AF_INET, SOCK_DGRAM, 0); 
60  if (sock < 0) error("Openingsocket"); 
61 
62  length = sizeof(server); 
63  bzero(&server,length); 
64 
65  /* Set the server address */ 
66  server.sin_family=AF_INET; 
67  server.sin_addr.s_addr=INADDR_ANY; 
68  server.sin_port=htons(atoi(argv[1])); 
69 
70  /* Bind the socket to the address */ 
71  if (bind(sock,(struct sockaddr *)&server,length)<0) 
72     error("binding"); 
73 
74  fromlen = sizeof(struct sockaddr_in); 
75  /* Infinite loop, receiving data and sending response */ 
76  while (1) { 
77     /* Receive data from socket. Parameters are: 
78        - server socket 
79        - buffer to read data into 
80        - maximum buffer size 
81        - flags to control the receive operation 
82        - structure to store source address 
83        - source address length 
84        */ 
85     n = recvfrom(sock,buf,1024,0,(struct sockaddr *)&from,&fromlen); 
86     if (n < 0) error("recvfrom"); 
87     write(1,"Receivedadatagram:",21); 
88     write(1,buf,n); 
89     /* Write data to socket. Parameters are: 
90       - server socket 
91       - data to write 
92       - length of data 
93       - flags to control send operation 
94       - destination address 
95       - length of destination address 
96       */ 
97     n = sendto(sock,"Gotyourmessage\n",17, 
98             0,(struct sockaddr *)&from,fromlen); 
99     if (n < 0) error("sendto"); 
100  } 
101}

19.5 TCP Sockets in Python

Now we present example implementions of clients and servers that can exchange data across the Internet, but implemented using Python. There is a TCP version and a UDP version of the client/server application. In addition there is an application that uses raw sockets to generate and send packets of any type.

19.5.1 Example Usage

The example application contains the server IP address (127.0.0.1), port (5005) and message (Hello World!) hardcoded into the Python source. The address used means the client and server run on the same computer (easy for testing, but not very useful). You should change them to the values appropriate for your setup.

Start the server in one terminal, and then start the client in another terminal. The client exchanges data with the server and then exits. The server remains running. The output on the server is:

$ python socket_tcp_server.py
Hello, World! from 127.0.0.1:56279

The output on the client is:

$ python socket_tcp_client.py
Connected to 127.0.0.1:5005
Thank you.
$

19.5.2 TCP Client

 
1""" 
2Demonstration of TCP client. See also socket_tcp_server.py. 
3""" 
4 
5import socket 
6 
7# Addresses and data 
8serverip = "127.0.0.1" 
9serverport = 5005 
10message = "Hello,World!" 
11 
12# Create a TCP stream socket with address family of IPv4 (INET) 
13s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
14 
15# Connect to the server at given IP and port 
16s.connect((serverip, serverport)) 
17print "Connectedto" + serverip + ":" + str(serverport) 
18 
19# Send the entire message 
20s.sendall(message) 
21 
22# Wait for a response (max of 1024 bytes) 
23response = s.recv(1024) 
24print response

19.5.3 TCP Server

 
1""" 
2Demonstration of TCP server. See also socket_tcp_client.py. 
3""" 
4 
5import socket 
6 
7# Addresses and data 
8serverport = 5005 
9message = "Thankyou." 
10 
11# Create a TCP stream socket with address family of IPv4 (INET) 
12s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
13 
14# Bind the socket to any IP address and the designated port 
15s.bind((, serverport)) 
16 
17# Listen for connect requests (up to 5 at a time) 
18s.listen(5) 
19 
20# Server continues forever accept client connections 
21while 1: 
22 
23      # Wait to accept a connection from a client 
24      # This creates a new socket 
25      clientsocket, clientaddress = s.accept() 
26 
27      # Wait for a request from the connected client (max of 1024 bytes) 
28      request = clientsocket.recv(1024) 
29      print request + "from" + clientaddress[0] + : + str(clientaddress[1]) 
30 
31      # Send the entire message 
32      clientsocket.sendall(message) 
33 
34      # Close the connection to client 
35      clientsocket.close()

19.6 UDP Sockets in Python

19.6.1 Example Usage

Similar to the TCP Python example, the addresses and messages are hardcoded in the source for the UDP example. You should change them to values appropriate for your setup.

Start the server in one terminal, and then start the client in another terminal. The client sends a message to the server and the server returns an acknowledgement. The client waits for 0.5 seconds and then repeats. To exit the client/server press Ctrl-C.

The output on the server is:

$ python socket_udp_server.py 
received message: Hello, World!
received message: Hello, World!
received message: Hello, World!
received message: Hello, World!
received message: Hello, World!
received message: Hello, World!
                                                                                      
                                                                                      
received message: Hello, World!

The output on the client is:

$ python socket_udp_client.py 
UDP target IP: 127.0.0.1
UDP target port: 5006
message: Hello, World!
received message: Ack
received message: Ack
received message: Ack
received message: Ack
received message: Ack
received message: Ack
received message: Ack
^C

19.6.2 UDP Client

 
1""" 
2Demonstration of UDP client. See also socket_udp_server.py. 
3""" 
4 
5import socket 
6import time 
7 
8# Addresses and data 
9serverip = "127.0.0.1" 
10serverport = 5006 
11message = "Hello,World!" 
12 
13print "UDPtargetIP:", serverip 
14print "UDPtargetport:", serverport 
15print "message:", message 
16 
17# Create a UDP datagram socket with address family of IPv4 (INET) 
18sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
19 
20# Send data forever (or until Ctrl-C) 
21while True: 
22 
23      # Send message to server 
24      sock.sendto(message, (serverip, serverport)) 
25 
26      # Wait for reply from server (max 1024 bytes) 
27      data, addr = sock.recvfrom(1024) 
28      print "receivedmessage:", data 
29 
30      # Wait for some time before sending the message again 
31      time.sleep(0.5)

19.6.3 UDP Server

 
1""" 
2Demonstration of UDP server. See also socket_udp_client.py. 
3""" 
4 
5import socket 
6 
7# Addresses and data 
8serverport = 5006 
9message = "Ack" 
10 
11# Create a UDP datagram socket with address family of IPv4 (INET) 
12sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
13 
14# Bind the socket to any IP address and the designated port 
15sock.bind((, serverport)) 
16 
17# Receive data forever (or until Ctrl-C) 
18while True: 
19 
20      # Wait for message from client (max 1024 bytes) 
21      data, clientaddr = sock.recvfrom(1024) 
22      print "receivedmessage:", data 
23 
24      # Send message to client 
25      sock.sendto(message, clientaddr)

19.7 Raw Sockets in Python

TCP and UDP sockets provide an interface for an application to send/receive data using the respective transport protocol. In turn, both TCP and UDP use IP, which creates an IP datagram and sends it via the NIC. Raw sockets provide an interface for an application to create any type of packet and send via a chosen network interface. It provides the application direct access to send a data link layer packet (e.g. Ethernet frame), rather than having to go via TCP/IP.

Most applications don’t need raw sockets, as TCP or UDP sockets provide a much simpler interface for the service required by the application. However there are special cases when raw sockets may be used. For example, you can create packets of any format to send via a network interface for testing purposes (testing the network, testing the security of a system). Also you can capture packets of any type using raw sockets (e.g. implement your own “tcpdump”).

The following code provides an example of using raw sockets to create two types of packets:

  1. An Ethernet frame carrying the data Hello. The frame is sent to another computer on the LAN (hardcoded to be 192.168.1.1). Although the frame is sent, the receiving computer will most likely not do anything with the frame as there is no network layer protocol to pass the received data to.
  2. An Ethernet frame carrying an IP datagram. Inside the IP datagram is an ICMP packet, in particular an ICMP Echo Request used by ping. Again this is sent to a hardcoded destination address, with the intention that when this computer receives the Ethernet frame it will respond with an ICMP Echo Reply.

The example Python application demonstrates how to create the two frames to be sent. The code creates the frames in their raw binary format (although using hexadecimal values instead of binary). The frames, including source/destination MAC addresses, source/destination IP addresses, packet sizes, and checksums, are hardcoded in the Python source. This wil not run on your computer: you will at least need to change the addresses and checksums. Read the source code to see suggestions on how to do this.

The application sends the two frames and then exits. To test whether it worked you should capture using tcpdump on both the sending computer and the destination computer.

 
1""" 
2Demonstration of a raw socket to send arbitrary Ethernet packets 
3Includes two packet examples: Ethernet frame, ICMP ping request 
4Based on: https://gist.github.com/cslarsen/11339448 
5""" 
6 
7import socket 
8 
9# Addresses and data 
10interface = "eth0" # Set this to your Ethernet interface (e.g. eth0, eth1, ...) 
11protocol = 0 # 0 = ICMP, 6 = TCP, 17 = UDP, ... 
12 
13# Create a raw socket with address family PACKET 
14s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW) 
15 
16# Bind the socket to an interface using the specific protocol 
17s.bind((interface,protocol)) 
18 
19# Create an Ethernet frame header 
20# - Destination MAC: 6 Bytes 
21# - Source MAC: 6 Bytes 
22# - Type: 2 Bytes (IP = 0x0800) 
23# Change the MAC addresses to match the your computer and the destination 
24ethernet_hdr = [0x00, 0x23, 0x69, 0x3a, 0xf4, 0x7d, # 00:23:69:3A:F4:7D 
25            0x90, 0x2b, 0x34, 0x60, 0xdc, 0x2f, # 90:2b:34:60:dc:2f 
26            0x08, 0x00] 
27 
28# ------------ 
29# First packet 
30# Lets create an Ethernet frame where the data is "Hello". The ethernet header 
31# is already created above, now we just need the data. Note that if you capture 
32# this frame in Wireshark it may report "Malformed packet" which means Wireshark 
33# does not understand the protocol used. Thats ok, the packet was still sent. 
34 
35# Frame structure: 
36# etherent_hdr | ethernet_data 
37#    14 B   |    5 B 
38 
39ethernet_data_str = "Hello" 
40 
41# Convert byte sequences to strings for sending 
42ethernet_hdr_str = "".join(map(chr, ethernet_hdr)) 
43 
44# Send the frame 
45s.send(ethernet_hdr_str + ethernet_data_str) 
46 
47 
48# ------------- 
49# Second packet 
50# Now lets create a more complex/realistic packet. This time a ping echo request 
51# with the intention of receiving a ping echo reply. This requires us to create 
52# the IP header, ICMP header and ICMP data with exact values of each field given 
53# as bytes. The easiest way to know what bytes is to capture a normal packet in 
54# Wireshark and then view the bytes. In particular look at the IP ahd ICMP 
55# checksums - they need to be correct for the receiver to reply to a ping Echo 
56# request. The following example worked on my computer, but will probably not 
57# work on your computer without modification. Especially modify the addresses 
58# and checksums. 
59 
60# Frame structure: 
61# etherent_hdr | ip_hdr | icmp_hdr | icmp_data 
62#    14 B   | 20 B |  16 B  |  48 B 
63 
64# Create IP datagram header 
65# - Version, header length: 1 Byte (0x45 for normal 20 Byte header) 
66# - DiffServ: 1 Byte (0x00) 
67# - Total length: 2 Bytes 
68# - Identificaiton: 2 Bytes (0x0000) 
69# - Flags, Fragment Offset: 2 Bytes (0x4000 = Dont Fragment) 
70# - Time to Line: 1 Byte (0x40 = 64 hops) 
71# - Protocol: 1 Byte (0x01 = ICMP, 0x06 = TCP, 0x11 = UDP, ...) 
72# - Header checksum: 2 Bytes 
73# - Source IP: 4 Bytes 
74# - Destination IP: 4 Bytes 
75ip_hdr = [0x45, 
76       0x00, 
77       0x00, 0x54, 
78       0x80, 0xc6, 
79       0x40, 0x00, 
80       0x40, 
81       0x01, 
82       0x36, 0x8a, # checksum - change this! 
83       0xc0, 0xa8, 0x01, 0x07, # 192.168.1.7 
84       0xc0, 0xa8, 0x01, 0x01] # 192.168.1.1 
85 
86# ICMP Ping header 
87# - Type: 1 Byte (0x08 = Echo request, 0x00 = Echo reply) 
88# - Code: 1 Byte (0x00) 
89# - Checksum: 2 Bytes (try 0x0000, then in Wireshark look at correct value) 
90# - Identifier: 2 Bytes 
91# - Sequence number: 2 Bytes 
92# - Timestamp: 8 Bytes 
93icmp_hdr = [0x08, 
94         0x00, 
95         0xc2, 0x4d, # checksum - change this! 
96         0x00, 0x00, 
97         0x00, 0x01, 
98         0xab, 0x5c, 0x8a, 0x54, 0x00, 0x00, 0x00, 0x00] 
99 
100# ICMP Ping data 
101# - Data: 48 Bytes 
102icmp_data = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
103         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
104         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
105         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
106         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
107         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] 
108 
109# Convert byte sequences to strings for sending 
110ethernet_hdr_str = "".join(map(chr, ethernet_hdr)) 
111ip_hdr_str = "".join(map(chr, ip_hdr)) 
112icmp_hdr_str = "".join(map(chr, icmp_hdr)) 
113icmp_data_str = "".join(map(chr, icmp_data)) 
114 
115# Send the frame 
116s.send(ethernet_hdr_str + ip_hdr_str + icmp_hdr_str + icmp_data_str)