Socket is a way of inter-process communication, it and other inter-process communication is a major difference: it can realize the inter-process communication between different hosts, most of the various services on our network are based on sockets to complete the communication, such as we browse the web every day, QQ chat, send and receive emails and so on. To solve the problem of process communication between two hosts on the network, we must first uniquely identify the process, in the TCP/IP network protocol, is through the (IP address, protocol, port number) ternary to identify the process, to solve the problem of process identification, there is a basis for communication.
This article focuses on TCP socket network programming using Python, assuming that you already have a preliminary knowledge of networking and basic syntax knowledge of Python.
TCP is a connection-oriented transport layer protocol, TCP Socket is based on a Client-Server programming model, the server side listens to the client's connection request, once the connection is established to transfer data. So the introduction of TCP socket programming is also divided into client-side and server-side:
I. Client Programming
Creating a socket
The first step is to create a socket, which you can do with socket, a function of the socket module in Python:
#Socket client example in python import socket #for sockets #create an AF_INET, STREAM socket (TCP) s = (socket.AF_INET, socket.SOCK_STREAM) print 'Socket Created'
function creates a socket and returns the descriptor of the socket, which will be used later in the related functions. The function takes two arguments:
Address Family: either AF_INET (for Internet inter-process communication) or AF_UNIX (for inter-process communication on the same machine).
Type: socket type, can be SOCKET_STREAM (streaming socket, mainly used for TCP protocol) or SOCKET_DGRAM (datagram socket, mainly used for UDP protocol)
Note: Because this article is mainly an overview of the process of Python Socket Programming, so will not be related to the function parameters, return values for a detailed introduction, you need to understand the relevant manuals can be viewed!
error handling
If the socket creation function fails, an exception is thrown that needs to be caught:
#handling errors in python socket programs import socket #for sockets import sys #for exit try: #create an AF_INET, STREAM socket (TCP) s = (socket.AF_INET, socket.SOCK_STREAM) except , msg: print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1] (); print 'Socket Created'
So we've created a socket so far, and we're going to use it to connect to a server, so let's do that.
Connecting to the server
As mentioned at the beginning of this article, sockets use (IP address, protocol, port number) to identify a process, so in order to communicate with the server, we need to know its IP address and port number.
Obtain the IP address of the remote host
Python provides a simple function to get the IP address of a remote host:
host = '' port = 80 try: remote_ip = ( host ) except : #could not resolve print 'Hostname could not be resolved. Exiting' () print 'Ip address of ' + host + ' is ' + remote_ip
Now that we know the IP address of the server, we can use the connect function to connect to a specific port on that IP. The following example connects to port 80 (which is the default port for HTTP services):
#Connect to remote server ((remote_ip , port)) print 'Socket Connected to ' + host + ' on ip ' + remote_ip
Run the program:
$ python Socket created Ip of remote host is 173.194.38.145 Socket Connected to on ip 173.194.38.145
Send data
The above shows that the connection has been successful, then we can send some data to the server, such as sending the string GET / HTTP/1.1\r\n\r\n, which is an HTTP request for web page content command.
#Send some data to remote server message = "GET / HTTP/1.1\r\n\r\n" try : #Set the whole string (message) except : #Send failed print 'Send failed' () print 'Message send successfully'
After sending the data, the client also needs to receive a response from the server.
receive data
The recv function can be used to receive data from a socket:
#Now receive data reply = (4096) print reply
The results of running them together are as follows:
Socket created Ip of remote host is 173.194.38.145 Socket Connected to on ip 173.194.38.145 Message send successfully HTTP/1.1 302 Found Cache-Control: private Content-Type: text/html; charset=UTF-8 Location: /?gfe_rd=cr&ei=PlqJVLCREovW8gfF0oG4CQ Content-Length: 262 Date: Thu, 11 Dec 2014 08:47:58 GMT Server: GFE/2.0 Alternate-Protocol: 80:quic,p=0.02 <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>302 Moved</TITLE></HEAD><BODY> <H1>302 Moved</H1> The document has moved <A HREF="/?gfe_rd=cr&ei=PlqJVLCREovW8gfF0oG4CQ">here</A>. </BODY></HTML>
Close socket
When we don't want to request data from the server again, we can close the socket and end the communication:
()
wrap-up
Above we learned how:
- Creating a socket
- Connecting to a Remote Server
- Send data
- receive data
- Close socket
When we open the It makes sense to know that this is what the browser does when it comes to sockets. A socket with this behavior is called a CLIENT, and the client mainly connects to the remote system to get data.
The other behavior in socket is called SERVER. The server uses socket to receive connections and provide data, which is the opposite of the client. So it's the server and your browser is the client, or more accurately, it's the HTTP server and your browser is the HTTP client.
So we've covered client-side programming, now it's the server's turn to use sockets.
II. Server-side programming
The server side does the following:
- Open socket
- Bind to a specific address and port
- monitor a connection
- establish a connection
- Receive/Send Data
Now that you've seen how to create a socket, the next step is to bind it.
Binding sockets
The bind function can be used to bind a socket to a specific address and port, and takes a sockaddr_in structure as an argument:
import socket import sys HOST = '' # Symbolic name meaning all available interfaces PORT = 8888 # Arbitrary non-privileged port s = (socket.AF_INET, socket.SOCK_STREAM) print 'Socket created' try: ((HOST, PORT)) except , msg: print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1] () print 'Socket bind complete'
Once the binding is complete, the next step is to listen for connections.
monitor a connection
The listen function puts the socket in listen mode:
(10) print 'Socket now listening'
This function takes a parameter called backlog, which controls the number of connections. If it is set to 10, then there are 10 connections waiting to be processed and the 11th request will be rejected.
receiver connection
When a client sends a connection request to the server, the server receives the connection:
#wait to accept a connection - blocking call conn, addr = () #display client information print 'Connected with ' + addr[0] + ':' + str(addr[1])
of running the program, the output is as follows:
$ python Socket created Socket bind complete Socket now listening
At this point, the program is waiting for a request to come in on port 8888. Don't close the program, leave it running, and the client can now connect to the socket on that port. let's test this with a telnet client by opening a terminal and typing telnet localhost 8888:
$ telnet localhost 8888 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Connection closed by foreign host.
This is what the server-side output will show:
$ python Socket created Socket bind complete Socket now listening Connected with 127.0.0.1:59954
We observe that the client has connected to the server. After establishing the connection, we can use it to communicate with the client. The following example demonstrates that after the server establishes the connection, it receives the data sent by the client and immediately sends the data back, below is the complete server side program:
import socket import sys HOST = '' # Symbolic name meaning all available interfaces PORT = 8888 # Arbitrary non-privileged port s = (socket.AF_INET, socket.SOCK_STREAM) print 'Socket created' try: ((HOST, PORT)) except , msg: print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1] () print 'Socket bind complete' (10) print 'Socket now listening' #wait to accept a connection - blocking call conn, addr = () print 'Connected with ' + addr[0] + ':' + str(addr[1]) #now keep talking with the client data = (1024) (data) () ()
Run this program in one terminal, open another terminal, use telnet to connect to the server, type in a random string and you'll see:
$ telnet localhost 8888 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. happy happy Connection closed by foreign host.
The client (telnet) receives a response from the server.
The server disconnects as soon as we finish a response, and servers like this are always waiting to receive connections. The easiest way to make the above server program run all the time is to put accept into a loop, and it will always receive connections.
Maintenance services
We can change the code to make the server work all the time like this:
import socket import sys HOST = '' # Symbolic name meaning all available interfaces PORT = 5000 # Arbitrary non-privileged port s = (socket.AF_INET, socket.SOCK_STREAM) print 'Socket created' try: ((HOST, PORT)) except , msg: print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1] () print 'Socket bind complete' (10) print 'Socket now listening' #now keep talking with the client while 1: #wait to accept a connection - blocking call conn, addr = () print 'Connected with ' + addr[0] + ':' + str(addr[1]) data = (1024) reply = 'OK...' + data if not data: break (reply) () ()
Now run the above server program in a terminal, and then open three terminals, respectively, with telnet to connect, if a terminal is connected to the other terminals without inputting data there is no way to connect, and each terminal can only be serviced once before disconnecting. This can also be seen from the code.
This is obviously not what we want, we want multiple clients to be able to establish a connection at any time, and each client can communicate with the server multiple times, how can this be modified?
process a connection
To handle each connection, we need to separate the program that handles it from the main program that receives the connection. One way to do this could be to use threads, where the main service program receives the connection, creates a thread to handle the communication for that connection, and then the server goes back to the logic of receiving the other connections.
import socket import sys from thread import * HOST = '' # Symbolic name meaning all available interfaces PORT = 8888 # Arbitrary non-privileged port s = (socket.AF_INET, socket.SOCK_STREAM) print 'Socket created' #Bind socket to local host and port try: ((HOST, PORT)) except , msg: print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1] () print 'Socket bind complete' #Start listening on socket (10) print 'Socket now listening' #Function for handling connections. This will be used to create threads def clientthread(conn): #Sending message to connected client ('Welcome to the server. Type something and hit enter\n') #send only takes string #infinite loop so that function do not terminate and thread do not end. while True: #Receiving from client data = (1024) reply = 'OK...' + data if not data: break (reply) #came out of loop () #now keep talking with the client while 1: #wait to accept a connection - blocking call conn, addr = () print 'Connected with ' + addr[0] + ':' + str(addr[1]) #start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function. start_new_thread(clientthread ,(conn,)) ()
Run the above program again and open three terminals to establish a telnet connection with the master server. At this time, the three clients can be accessed at any time, and each client can communicate with the master server several times.
The following output is possible in a telnet terminal:
$ telnet localhost 8888 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Welcome to the server. Type something and hit enter hi OK...hi asd OK...asd cv OK...cv
To end the telnet connection, press the Ctrl-] key and enter the close command.
The output from the server terminal might look like this:
$ python Socket created Socket bind complete Socket now listening Connected with 127.0.0.1:60730 Connected with 127.0.0.1:60731
So far, we've learned the basics of socket programming in Python, and there's more to come, so don't go away.