Appendix E
Python Sockets Examples

File: Steve/Courses/2014/s2/its332/python.tex, r3463

This appendix includes example implementation of clients and servers that can exchange data across the Internet. They are implemented in 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.

The source code can be downloaded via http://ict.siit.tu.ac.th/~sgordon/netlab/source/.

E.1 TCP Sockets in Python

E.1.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. 
$

E.1.2 TCP Client

 
1""" 
2DemonstrationofTCPclient.Seealsosocket_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

E.1.3 TCP Server

 
1""" 
2DemonstrationofTCPserver.Seealsosocket_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()

E.2 UDP Sockets in Python

E.2.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

E.2.2 UDP Client

 
1""" 
2DemonstrationofUDPclient.Seealsosocket_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)

E.2.3 UDP Server

 
1""" 
2DemonstrationofUDPserver.Seealsosocket_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)

E.3 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""" 
2DemonstrationofarawsockettosendarbitraryEthernetpackets 
3Includestwopacketexamples:Ethernetframe,ICMPpingrequest 
4Basedon: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 "Malformedpacket" 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 = DontFragment) 
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)