Documente Academic
Documente Profesional
Documente Cultură
To understand what sockets are, let's start with the Internet Connection. The Internet Connection
basically connects two points across the internet for data sharing and other stuff. One process from
computer C1 can communicate to a process from computer C2, over an internet connection. It has
following properties:
• Reliable: It means until the cables connecting two computers are safe, data will be
transfered safely.
• Point-to-Point: Connection is established between 2 points.
• Full-Duplex: It means transfer of information can occur in both ways i.e. from client to
server as well as server to client simultaneously(at the same time).
Sockets are the endpoints of a bidirectional, point-to-point communication channel. Given an
internet connection, say between client(a browser) and the server, we will have two sockets. A
Client Socket and a Server Socket.
Vaguely speaking, when you clicked on the link that brought you to a website, your browser did
something like the following:
#a socket object is created for communication
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
This happened on the client side. When the client tries to connect with the server, a random port is
assigned by the operating system for the connection. This random port is called Ephermal Port. In
the above illustration, 1300 is an ephermal port on the source(client) machine. The client socket is
short lived, i.e as soon as the data exchange ends it closes. Now what happens on server is a bit
different from client. So,let's see:
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Connect is used by the client socket to start a connection with the server. This request is fulfilled by
bind method of the server socket. If you are having problem with the code, don't worry. Every bit of
it will be explained separately with examples.
Before concluding, let's see some differences between the client and the server sockets:
• Unlike client sockets, server sockets are not short lived. For example: you might need
youtube.com for a single request but youtube.com has to be up 24*7 for any request which it
might receive from users across the globe.
• Unlike client socket which uses Ephermal Port for connection, server socket requires a
standard or well defined port for connection like: Port 80 for Normal HTTP Connection,
Port 23 for Telnet etc.
Python Sockets - SOCK_STREAM and
SOCK_DGRAM
There are two type of sockets: SOCK_STREAM and SOCK_DGRAM. Below we have a comparison
of both types of sockets.
SOCK_STREAM SOCK_DGRAM
For TCP protocols For UDP protocols
Reliable delivery Unrelible delivery
Guaranteed correct ordering of packets No order guaranteed
Connection-oriented No notion of connection(UDP)
Bidirectional Not Bidirectional
• socket_family: This is either AF_UNIX or AF_INET. We are only going to talk about INET
sockets in this tutorial, as they account for at least 99% of the sockets in use.
• socket_type: This is either SOCK_STREAM or SOCK_DGRAM.
• Protocol: This is usually left out, defaulting to 0.
Now, if you remember we have discussed client-server socket program . Now let's dig deeper into
that program and try to understand the terms and methods used.
connect( )
To connect to a remote socket at an address. An address format(host, port) pair is used for
AF_INET address family.
bind( )
This method binds the socket to an address. The format of address depends on socket family
mentioned above(AF_INET).
listen(backlog)
This method listens for the connection made to the socket. The backlog is the maximum number of
queued connections that must be listened before rejecting the connection.
accept( )
This method is used to accept a connection. The socket must be bound to an address and listening
for connections. The return value is a pair(conn, address) where conn is a new socket
object which can be used to send and receive data on that connection, and address is the address
bound to the socket on the other end of the connection.
while True:
conn,addr = s.accept() #line 7: connect and accept from client
print 'Got Connection from', addr
conn.send('Server Saying Hi')
conn.close() #line 8: Close the connection
This script will do nothing as of now. It waits for a client to connect at the port specified. If we run
this script now, without having a client, it will wait for the connection,
Similarly, every website you visit has a server on which it is hosted, which is always waiting for
clients to connect. Now let's create a client.py program and try to connect with our
server.py.
import socket
s = socket.socket()
host = socket.gethostname() # Get current machine name
port = 9999 # Client wants to connect to server's
# port number 9999
s.connect((host,port))
print s.recv(1024) # 1024 is bufsize or max amount
# of data to be received at once
s.close()
Now, run the server.py script first(if you haven’t yet) and then run the client.py script. If
everything goes well, you will see the output as follows:
Note: Here we are running both client and server on the same machine but a real life scenario is
surely different from this, but is similar.
Notice that after executing, terminates but server.py is still running. This is what happens in
real scenario too. After fulfiling your request, the server keeps on running 24*7 to serve other users.
After executing client.py, server says: Got Connection from ('192.168.43,217', 43402). Here
port 43402 is random or ephemeral port assigned to the client by the operating system.
Flow Diagram of the Program
Working with UDP Sockets
Well, we defined socket as:
S = socket.socket(socket_family, socket_type, protocol = 0)
But, we have covered TCP sockets we defined TCP socket by merely writing
S=socket.socket(), that is without providing the socket_family and the socket_type. If we
do not mention the socket_family and socket_type, then by default it is TCP. So, if we want to
create a UDP socket than we have to specify socket_family and socket_type explicitly.
For UDP socket we define:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
import socket
sock.bind((udp_host,udp_port))
while True:
print "Waiting for client..."
data,addr = sock.recvfrom(1024) #receive data from client
print "Received Messages:",data," from",addr
Output of the above script is as follows. Keep it running and than fire up the client.py module.
Simple UDP Client
This is the udpclient.py script:
#!usr/bin/python
import socket
Our udpserver.py is up and running, so now we try to run the udpclient.py script,
And here is what happened to our server after the client sends the request:
Flow Diagram of the Program
So, we have learnt how to setup a successful Client-Server connection using both TCP socket and
UDP sockets.
Handling Received Client Data over TCP
Socket
Now we will have an example in which the client sends some data to the server and the server
handles the data as instructed. We'll see two different usecases for this:
• Echo Client-Server Program
• Handling received data by adding them
import socket
host = socket.gethostname()
port = 12345
s = socket.socket() # TCP socket object
s.bind((host,port))
s.listen(5)
while True:
data = conn.recv(1024) # Receive client data
if not data: break # exit from loop if no data
conn.sendall(data) # Send the received data back to client
conn.close()
import socket
host = socket.gethostname()
port = 12345
s = socket.socket() # TCP socket object
s.connect((host,port))
Now, as the server is already up and running, we should run our echo_client.py
import socket
host = socket.gethostname()
port = 12345
s = socket.socket() # TCP socket object
s.bind((host,port))
s.listen(5)
add_client.py
#!usr/bin/python
import socket
host = socket.gethostname()
port = 12345
s = socket.socket()
s.connect((host,port))
Output:
Blocking and Non-Blocking Socket I/O
In client server applications, when a client makes a request to a server, server processes the request
and sends back a response. For this, both the client and the server first needs to establish a
connection with one another through sockets (TCP or UDP). we also saw, how a client can send
data in form of request to the server and the server can operate on it, and then send a response back
to the client.
import socket
sock = socket.socket()
host = socket.gethostname()
sock.connect((host, 12345))
sock.setblocking(1)
#block_server.py
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.bind((host,port))
s.listen(5)
while True:
conn, addr = s.accept() # accept the connection
data = conn.recv(1024)
while data: # till data is coming
print data
data = conn.recv(1024)
print "All Data Received" # Will execute when all data is received
conn.close()
break
Now, run block_server.py first and then block_client.py. You'll notice that the server
keeps on printing Hello Python. This will go on and on till all the data is sent. In the above code the
line All Data Received will not be printed for long time, because as the client has to send a large
number of string, which will take time, and until then the socket input-output will get blocked.
What's going on here? The send() method will try to transmit all the data to the server, while the
write buffer will get filled up. The kernel will put the process to sleep until the data in the buffer is
transferred to the destination and the buffer is empty again. When the buffer becomes empty, the
kernel will wake the process up again to get the next chunk of data that is to be transferred. In short,
your code will block and it will not let anything else proceed.
# non_blocking_client.py
import socket
sock = socket.socket()
host = socket.gethostname()
sock.connect((host, 12345))
sock.setblocking(0) # Now setting to non-blocking mode
TSL/SSL
Before diving into the depth of TSL and SSL, we should first understand what is Encryption.
According to wikipedia, "Encryption is the process of encoding a message or information in such a
way that only authorized parties can access it. In an encryption scheme, the intended information
or message, referred to as plaintext, is encrypted using an encryption algorithm, generating
ciphertext that can only be read if decrypted."
Encryption is necessary to ensure the confidentiality of message/data.
TLS(Transport Layer Security) and SSL(Secure Sockets Layer) are protocols that provide data
encryption and authentication between applications and servers in scenarios where that data is being
sent across an insecure network.
The terms SSL and TLS are often used interchangeably, but one is in fact the predecessor of the
other — SSL 3.0 served as the basis for TLS 1.0 which, as a result, is sometimes referred to as SSL
3.1.
SSL Handshake
For SSL/TLS handshake to take place, the system administrator must have:
• Private Key: Used for data encryption.
• Certificate: To ensure the authenticity of client.
Although SSL handshake is a bit more complex. We will explain it in simplest possible way.
Building a custom Port Scanner using Sockets
port_scanner.py
#!usr/bin/python
#port_scanner.py
import socket
while 1:
t_port = int(raw_input("Enter the port: ")) # Enter the port to
be scanned
try:
sock = socket.socket()
res = sock.connect((t_ip, t_port))
print "Port {}: Open" .format(t_port)
sock.close()
except:
print "Port {}: Closed" .format(t_port)
When you run the above program, it prompts you to enter a hostname(www.example.com) and
then it keeps on asking for port numbers you want to scan.
To terminate the program, press Ctrl + C.
Output:
Using the Nmap Port Scanner with Python
What is Nmap?
Nmap(Network Mapper) is a security scanner, originally written by Gordon Lyon(also known by
his pseudonym Fyodor Vaskovich), and used to discover hosts and services on a computer network,
thereby building a map of the network. To accomplish its goal, Nmap sends specially crafted
packets to the target host(s) and then analyzes their responses.
Some of the useful Nmap features include:
• Host Discovery: This enables to identify hosts on any network. For example, listing the
hosts that respond to TCP and/or ICMP requests or have a particular port open.
• Port Scanning: Enumerating(counting and listing one by one) all the open ports on the
target hosts.
• Version Detection: Interrogating network services on remote devices to determine
application name and version number.
• OS Detection: Determining the operating system and hardware characteristics of the
network devices.
• Scriptable Interaction with the target: Using Nmap Scripting Engine(NSE) and Lua
programming language, we can easily write sripts to perform operations on the network
devices.
Although Nmap is a command line interface, you can download and install the GUI interface for
Nmap known as zenmap.
Above is the screenshot of the command line, when you run nmap command, all the options
available for Target specifications and Host discovery, Scan Techniques etc are listed for your
assistance. In case you want to install nmap in your machine, then:
• Run, sudo apt-get install nmap for Linux.
• For Windows and Mac OS X, download and install Nmap: https://nmap.org/download.html
The Port scanner program provides a quick script for performing a TCP connect scan. This is very
limited as we might require the ability to perform additional scan types such as ACK, RST, FIN, or
SYN-ACK scans provided by the Nmap toolkit. Nmap, delivers a rather extensive amount of
functionality. This begs the question, why not just use Nmap? Why bother about writing a script for
Port scanner?
Nmap is written in C and LUA programming languages, and can be easily integrated into Python.
Nmap produces XML based output which provides us with the ability to utilize the full functionality
of Nmap from within a Python script. So our Port Scanner script is just the outer shell, inside it we
will be using Nmap now.