Vamei Source: Http://www.cnblogs.com/vamei Welcome reprint, Please also keep this statement. Thank you!
In my previous Python tutorial, there was a message that it was useless to learn python, and that you had to learn a framework (like Django and web.py) to find work. My idea is that mastering a high-level tool like a framework is useful, but the basics can make you never be eliminated. Do not be limited by the tools of their own development. Today, what I want to show here is not using the framework, or even using the advanced package in the Python standard library, using only the socket interface in the standard library (I don't quite understand the socket translation, so use the socket's English name) and write a Python server.
In the age of today's Python server frameworks (the framework, such as Django, Twisted, web.py, and so on), starting from the bottom of the socket to write a server seems like a clumsy way to do something. The meaning of the framework is to cover up the underlying details, provide a set of APIs that are more user-friendly to developers, and handle layout problems such as MVC. The framework allows us to quickly build a well-formed and mature python server. However, the framework itself is also dependent on the underlying (such as sockets). Understanding the underlying sockets not only helps us to better use the framework, but also allows us to understand how the framework is designed. Further, if you have good knowledge of the underlying socket programming and other system programming, you can design and develop a framework of your own. If you can start with the underlying socket, implement a full Python server, support the user layer protocol, and handle issues such as MVC (Model-view-control), Multithreading (threading), and sort out a clear set of functions or classes as interfaces (API) is presented to the user, you are the equivalent of designing a framework.
The socket interface is actually a system call provided by the operating system. The use of sockets is not limited to the Python language, you can use C or Java to write the same socket server, and all languages using the socket is similar (Apache is the use of C implementation of the server). And you can't use a framework across languages. The benefit of the framework is that it helps you deal with some of the details, allowing for rapid development, but is also limited by the performance of Python itself. We've seen that many successful sites are developed quickly using dynamic languages such as Python, Ruby or PHP, such as Twitter and Facebook, to translate the code into more efficient languages such as C and Java after the site is successful. This allows the server to be more efficient in facing hundreds of thousands of requests per day. At such times, the importance of the bottom is far beyond the framework.
The following article is talking about Java, but I think it also applies to Python's frame contention.
http://yakovfain.com/2012/10/11/the-degradation-of-java-developers/
TCP/IP and sockets
We need to have a certain understanding of the network transmission, especially the TCP/IP protocol and socket. Sockets are a way of interprocess communication (refer to Linux interprocess communication), which is an upper-level interface based on the network transport protocol. There are many types of sockets, such as TCP protocol or UDP protocol (two kinds of network transport protocols). TCP sockets are the most commonly used. A TCP socket is similar to a bidirectional pipe (duplex pipe) where a process writes or reads a stream of text to one end of the socket, while another process can read or write from the other end of the socket, and in particular, The two processes that establish the socket communication can belong to two different computers, respectively. The so-called TCP protocol, is to provide a number of communication codes, in order to effectively implement the above-mentioned interprocess communication process in the network environment. The two-way pipe (duplex pipe) survives on the same computer, so it is not necessary to differentiate the address of the computer where the two processes are located, and the socket must contain address information to enable network communication. A socket contains four address information: the IP address of the two computers and the port used by the two processes. The IP address is used to locate the computer, and port is used to locate the process (multiple processes can use different ports on a single computer).
A TCP socket-connected network
TCP sockets
On the Internet, we can make a computer as a server. The server opens its own port and passively waits for other computers to connect. When other computers act as clients, the server begins to service the client when it actively uses the socket to connect to the server.
In Python, we use the socket package in the standard library for the underlying socket programming.
The first is the server side, we use the bind () method to give the socket a fixed address and port, and use the Listen () method to passively listen to the port. When a client attempts to connect using the Connect () method, the server uses the accept () connection to establish a connected socket:
# written by vamei# Server Sideimport socket
# addresshost = ' PORT = 8000reply = ' Yes '
# Configure Sockets = Socket.socket (socket.af_inet, socket. Sock_stream) S.bind ((HOST, PORT))
# passively Wait, 3:maximum number of connections in the Queues.listen (3)
# Accept and establish connectionconn, addr = S.accept ()
# receive Messagerequest = CONN.RECV (1024)
print ' request is: ', Requestprint ' Connected by ', addr
# Send Messageconn.sendall (Reply)
# Close Connectionconn.close ()
Socket.socket () Creates a socket object and indicates that the socket is using IPV4 (AF_INET,IP version 4) and the TCP Protocol (SOCK_STREAM).
Then use another computer as the customer, we actively use the Connect () method to search the server-side IP address (in Linux, you can use $ifconfig to query their own IP address) and port, so that customers can find the server and establish a connection:
# written by vamei# Client Sideimport socket
# addresshost = ' 172.20.202.155 ' PORT = 8000request = ' Can you hear me? '
# Configure Sockets = Socket.socket (socket.af_inet, socket. Sock_stream) S.connect ((HOST, PORT))
# Send Messages.sendall (Request)
# Receive messagereply = S.RECV (1024x768) print ' reply is: ', reply
# Close Connections.close ()
In the above example, we can call the Recv () method on both ends of the socket to receive the message and call the Sendall () method to send the message. In this way, we can communicate between the two processes that are in the two computers. When the communication is over, we use the close () method to close the socket connection.
(If you do not have two computers to experiment, you can also change the IP of the client IP to connect to "127.0.0.1", this is a special IP address to connect to the local host.) )
TCP socket-based HTTP server
In the above example, we can already use a TCP socket to establish a connection to two remote computers. However, the socket transfer freedom is too high, resulting in a lot of security and compatibility issues. We often use some application-layer protocols, such as the HTTP protocol, to specify the socket usage rules and the format of the transmitted information.
The HTTP protocol uses a request-response (Request-response) method to use a TCP socket. The client sends a piece of text to the server as a request, and after the server receives the request, a text is sent to the client as a response. After such a request-response transaction is completed, the TCP socket is discarded. The next request will create a new socket. Request and response are essentially two texts, but the HTTP protocol has some formatting requirements for both texts.
Request-response Cycle
Now, let's write an HTTP server side:
# written by vameiimport socket# addresshost = ' PORT = 8000# Prepare HTTP responsetext_content = ' http/1.x OK Cont Ent-type:text/html
# Read picture, put into HTTP FORMATF = open (' test.jpg ', ' RB ') pic_content = ' http/1.x OK content-type:image/jpg ' p Ic_content = pic_content + f.read () f.close () # Configure sockets = Socket.socket (socket.af_inet, socket. Sock_stream) S.bind ((HOST, PORT)) # infinite loop, Server foreverwhile True: # 3:maximum number of requests waiting s . Listen (3) conn, addr = s.accept () request = CONN.RECV (1024x768) method = Request.split (") [0] src = Request.split (") [1] # deal with Get method if method = = ' GET ': # ULR if src = = '/test.jpg ': Content = pic_content else:content = text_content print ' Connected by ', addr print ' Requ EST is: ', request Conn.sendall (content) # Close connection Conn.close ()
Dive into the HTTP server program
As we can see above, the server will transmit two messages to the customer according to request Text_content and one of the pic_content, as response text. The whole response is divided into the starting line, the head information (head) and the body (body) three parts. The starting line is the first line:
http/1.x OK
It is actually divided into three fragments by the space, http/1.x for the HTTP version used, 200 for the State (status code), and 200 for the HTTP protocol, indicating that the server normally receives and processes the request, OK is the status code for people to read.
The header information follows the starting line, and there is a blank line between it and the body. Here Text_content or pic_content have only one row of header information, text_content is used to represent the type of the principal information as HTML text:
Content-type:text/html
The Pic_content header information (content-type:image/jpg) describes the type of the body as a JPG picture (image/jpg).
The principal information is the contents of an HTML or JPG file.
(Note that for JPG files, we use the ' RB ' mode to open it for compatibility with Windows.) Because JPG is considered a binary (binary) file under Windows, there is no need to differentiate between text files and binaries under Unix systems. )
We did not write the client program, we will use the browser as the client later. Request is sent to the server by the client program. Although request can be divided into three parts like response, the request format is not the same as the response format. The request is sent by the client to the server, such as the following request:
Get/test.jpg http/1.xaccept:text/*
The starting line can be divided into three parts, the first part is the request method, the second part is the URL, the third is the HTTP version. The request method can have get, PUT, POST, DELETE, HEAD. The most common are get and post. Get is the request server to send resources to the customer, post is the request server to receive the data sent by the customer. When we open a webpage, we usually use the Get method, and when we fill out the form and submit it, we usually use the post method. The second part is the URL, which usually points to a resource (a resource on the server or a resource elsewhere). As it is now, it is the test.jpg of the current directory that points to the current server.
As specified in the HTTP protocol, the server needs to perform certain operations on request. As we saw in the server program, our Python program first examines the request method and then generates different response (text_content or pic_content) depending on the URL. The response is then sent back to the client.
Experimenting with browsers
To match the above server program, I have saved a test.jpg image file in the folder where the Python program was placed. We run the above Python program at the terminal, as the server side, and then open a browser as the client. (If you have time, you can also write a client in Python.) The principle is similar to the client program of the TCP socket above. )
In the address bar of the browser, enter:
127.0.0.1:8000
(Of course, you can also use to make a computer and enter the IP address of the server.) I get the following result:
OK, I already have a server that is implemented in Python and is written from the socket.
From the terminal, we can see that the browser actually sends out two requests. The first request is (the key information is in the starting line, the principal of this request is empty):
get/http/1.1host:127.0.0.1:8000user-agent:mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:14.0) gecko/20100101 firefox/14.0.1accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q= 0.8accept-language:en-us,en;q=0.5accept-encoding:gzip, Deflateconnection:keep-alive
Our Python program sends the contents of the server text_content according to this request.
After the browser receives the text_content, the Discovery body HTML text has , knowing that a text.jpg file needs to be added as a picture, a second request is immediately issued:
Get/test.jpg http/1.1host:127.0.0.1:8000user-agent:mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:14.0) gecko/20100101 firefox/14.0.1accept:image/png,image/*;q=0.8,*/*;q=0.5accept-language:en-us,en;q= 0.5accept-encoding:gzip, Deflateconnection:keep-alivereferer:http://127.0.0.1:8000/
After analyzing the starting line, our Python program finds that/test.jpg meets the IF condition, so the pic_content is sent to the customer.
Finally, the browser displays HTML text and drawings in an appropriate way, based on the syntax of the HTML language. (HTML can refer to http://www.w3schools.com/html/default.asp)
The direction of exploration
1) in our server program above, we use the while loop to keep the server working. In fact, we can change the contents of the while loop to multi-process or multi-threaded work, based on the multithreading knowledge I've described earlier. (Refer to Python Multi-threading and synchronization, Python multi-process preliminary, Python multi-process exploration)
2) Our server program is not perfect, we can also let our Python program call Python's other features to achieve more complex functions. For example, make a time server and let the server return the date and time to the customer. You can also use Python's own database to implement a complete lamp server.
3) The socket package is the lower-level package. There are also high-level packages in the Python standard library, such as socketserver,simplehttpserver,cgihttpserver,cgi. These are all packages that help us to use the socket more easily. If you already know the socket, these packages are easy to understand. With these high-level packages, you can write a fairly mature server.
4) After all the hard work and trouble, you may find that the framework is so convenient that you decide to use the framework. Or, you already have the passion to participate in the development of the framework.
More content
TCP/IP and Port reference: TCP/IP Illustrated http://book.douban.com/subject/1741925/
Socket reference: UNIX Network Programming http://book.douban.com/subject/1756533/
Python Socket Official Document Http://docs.python.org/2/library/socket.html
HTTP reference: HTTP, the definitive guide http://book.douban.com/subject/1440226/
Welcome to the Python quick tutorial
Python app 01 original python server