Python has been around for years, and in past few years it has become de-facto language for Data Network Programming and Scripting. The simple reason is ease of use and inbuilt libraries. This article intends to give a preview to network admins/engineers who might have networking knowledge but may have never worked with
Python or scripting at all. You really don’t need much, simplicity of the Python language should auto explain most of the concepts combined with your existing networking skills.
For purpose of this article, we assume you understand basic data networking concepts such as IP, Port, Socket, Hostname, Server and Client. You will need two things to run the code in this article, latest Python Interpreter (we recommend Python 3+ downloadable – https://www.python.org/downloads/) and a Python supported IDE (we
recommend PyCharm – https://www.jetbrains.com/pycharm/download/) – both are free, for PyCharm Community Edition is good enough or you may use any other IDE so long it supports Python3+. First install Python and then install PyCharm for purpose of this article (or you may use vi or emac editor on your linux/mac environment).
Python Background: Python is a widely used high-level programming language for general-purpose programming, first released in 1991. An interpreted language, Python has a design philosophy that emphasizes code readability (notably using whitespace indentation to delimit code blocks rather than curly braces or keywords), and a syntax that allows programmers to express concepts in fewer lines of code than possible in languages such as C++ or Java. The language provides constructs intended to enable writing clear programs on both a small and large scale. Python features a dynamic type system and automatic memory management and supports multiple programming
paradigms, including object-oriented, imperative, functional programming, and procedural styles. It has a large and comprehensive standard library.
Skip below section if you already familiar with TCP/IP, Socket, and Ports:
Quick Review – Data Networking and Socket Programming: In practice “socket” usually refers to a socket in an Internet Protocol (IP) network (where sockets may be called Internet sockets), in particular for the Transmission Control Protocol (TCP), which is a protocol for one-to-one connections. In this context, sockets are assumed to be associated with a specific socket address, namely the IP address and a port number for the local node, and there is a corresponding socket address at the foreign node (other node), which itself has an associated socket, used by the foreign process. Associating a socket with a socket address is called binding.
Note that while a local process can communicate with a foreign process by sending or receiving data to or from a foreign socket address, it does not have access to the foreign socket itself, nor can it use the foreign socket descriptor, as these are both internal to the foreign node. For example, in a connection between 10.20.30.40:4444 and 18.104.22.168:8888 (local IP address:local port, foreign IP address:foreign port), there will also be an associated socket at each end, corresponding to the internal representation of the connection by the protocol stack on that node, which are referred to locally by numerical socket descriptors, say 317 at one side and 922 at the other. A process on node 10.20.30.40 can request to communicate with node 22.214.171.124 on port 8888 (request that the protocol stack create a socket to communicate with that destination), and once it has created a socket and received a socket descriptor (317), it can communicate via this socket by using the descriptor (317): the protocol stack will then forward data to and from node 126.96.36.199 on port 8888. However, a process on node 10.20.30.40 cannot request to communicate with “socket 922” or “socket 922 on node 188.8.131.52”: these are meaningless numbers to the protocol stack on node 10.20.30.40.
To summarize, sockets are the fundamental “things” behind any kind of network communications done by your computer. For example when you type www.google.com in your web browser, it opens a socket and connects to google.com to fetch the page and show it to you. Same with any chat client like imessenger or gtalk or skype. Any
network communication goes through a socket. In this article we shall be programming TCP sockets in python.
Enough of theory, now let’s get into programming brass stacks, first goal, creating a socket.
Creating a socket: Using PyCharm (or any IDE of your choice or you may simply use vi editor), create a new python file; call it client.py, and type in following code.
The socket library function socket.socket creates a new socket and returns a socket descriptor that may be used in other socket related functions. The above code will create a socket with the following properties:
Address Family: AF_INET (this is IP version 4 or IPv4)
Type: SOCK_STREAM (this means connection oriented TCP protocol)
Now open a terminal, cd (change directory) to where you have saved your client.py file,
and type in:
Bingo! Your socket is created – congratulations. If for some reason, python command is not executed, please check if you are able to issue python command (which python on Unix/Mac), make sure python is installed and if on windows machine, python path is in your environment (echo $PATH). Linux and Mac have python 2+ inbuilt but our examples are tested and designed for Python 3+.
What happens if there is an error? Well, we can use Python error handling mechanism (try block) to return give us a message, modify client.py as following and rerun the program, it should print error if unable to create a socket:
Connecting to a Server: Next, we connect to a remote server on a certain port number. For this, we need two things, an IP address and a port number. In this example, we will use IP address of google.com, just because its’ easy to find and thanks to Google, they do allow search
Lets modify our client.py file to get this IP address of nearest Google web server.
Rerun client.py on your terminal:
You should be able to pull the IP address of Google server near you! Next we should try to send some message to this server connection.
Sending Data: The socket library function sendall() will simply send data. Let’s send some data to google.com. We first connect to an IP address and then sends the string message “GET / HTTP/1.1rnrn” to it. The message is actually an “http command” to fetch the landing page of a website.
Try to run in the terminal, you should get something like:
Receiving Data: Python socket library function recv is used to receive data on a socket. Let’s try to receive message from google.com after we have sent http command to it. Just displaying changed try block in client.py with new response variable, rest of the code is same.
Try to run in the terminal, you should get something like:
Google web server replied with the content of the page we requested. Quite simple! Now that we have received our reply, it’s time to close the socket, last line.
It’s useful to know that your web browser also does the same thing when you open www.google.com. This kind of socket activity represents a client. A client is a system that connects to a remote system to fetch data. The other kind of socket activity is called a server. A server is a system that uses sockets to receive incoming connections and provide them with data. It is just the opposite of client. The website www.google.com is a server and your web browser is a client. Or more technically www.google.com is a HTTP Server and your web browser is an HTTP client. Now its time to do some server tasks using sockets.
Server Socket Programming: Servers basically do the following:
- Open a socket
- Bind to an address (and port).
- Listen for incoming connections.
- Accept connections
We have already learnt how to open a socket. Next thing would be to bind it. The socket library function bind can be used to bind a socket to a particular address and port. It needs a sockaddr_in structure similar to connect function. Let’s create a new python file using PyCharm, server.py and type following code:
Try to run this file, python server.py:
Since bind is done, its time to make the socket listen to connections. We bind a socket to a particular IP address and a certain port number. By doing this we ensure that all incoming data that is directed towards this port number is received by this application. This makes it obvious that you cannot have two sockets bound to the same port. There
are exceptions to this rule but we shall look into that in some other article. After binding a socket to a port the next thing we need to do is listen for connections. For this we need to put the socket in listening mode. The function socket_listen is used to put the socket in listening mode. Just add the following line after bind.
The parameter of the function listen is called backlog. The backlog controls the number of incoming connections that are kept “waiting” if the program is already busy. By specifying 10, it means that if 10 connections are already waiting to be processed, and then the 11th connection request shall be rejected. This will be much clearer after
Accept Connection, modify server.py file:
Run the server program:
This program is waiting for incoming connections on port 9999. Don’t close this program, keep it running. Now a client can connect to it on this port. We shall use the telnet client for testing this. Open a terminal and type:
It will immediately show:
And the server output will show
We can see that the client is connected to the server. We accepted an incoming connection but closed it immediately. This may not be very productive. There are lots of things that can be done after an incoming connection is established. After all the connection was established for the purpose of communication. So lets reply to the
client. The socket library function sendall can be used to send something to the socket of the incoming connection and the client should see it, code:
Run the above code in terminal. And connect to this server using telnet from another terminal and you should see this:
The client (telnet) received a reply from server. We can see that the connection is closed immediately after that simply because the server program ends after accepting and sending reply. Servers such as www.google.com are always up to accepting incoming connections. It means that a server is supposed to be running all the time. After all it’s a server meant to serve. So we need to keep our server RUNNING non-stop. The simplest way to do this is to put accept in a loop so that it can receive incoming connections all the time, lets code:
Run the server program in a terminal, and open three other terminals. From each of the three terminals do a telnet to the server port. Each of the telnet terminals would show:
The server is running nonstop and the telnet terminals are also connected nonstop. Now close the server program. All telnet terminals would show “Connection closed by foreign host.” But still there is not effective communication between the server and the client. The server program accepts connections in a loop and just sends them a reply,
after that it does nothing with them. Also it is not able to handle more than one connection at a time. It’s time to handle the connections, and handle multiple connections together.
Handling Connections: To handle every connection we need a separate handling code to run along with the main server accepting connections. One way to achieve this is using threads. The main server program accepts a connection and creates a new thread to handle communication for the connection, and then the server goes back to
accept more connections. We shall use threads to create handlers for each connection the server accepts. Notice how we have imported python thread library.
Run the above server and open few terminals like before. Now the server will create a thread for each client connecting to it. The telnet terminals would show:
The server terminal might look like this
The above connection handler takes some input from the client and replies back with the same. Congrats, now we have a server that’s communicative.
In Conclusion: We hope your learned the basics of socket programming in python. Python language is wonderful and simplistic language with plenty of inbuilt library for network programming. Further, there is plenty of third party networking components available. In future, we will explain beyond sockets, IP, bind, client, server and thread
programming. Stay tuned. – Python and Networking team – IrisLogic.