Python network programming

Source: Internet
Author: User
Tags socket blocking domain name server
Socket is the network connection endpoint. I. Introduction to Network Knowledge

Socket is the network connection endpoint. For example, when your Web browser requests the homepage of www.bitsCN.com, your Web browser creates a socket and commands it to connect to the Web server host of www.bitsCN.com, the Web server also listens to requests from a socket. Both ends use their respective sockets to send and receive information.

During use, each socket is bound to a specific IP address and port. An IP address is a sequence composed of four numbers, all of which are in the range of 0 ~ Value in 255 (for example, 220,176,); value range of port value is 0 ~ 65535. All ports smaller than 1024 are reserved for well-known network services (such as port 80 used by Web services); the maximum number of ports is stored in the IPPORT_RESERVED variable of the socket module. You can also use another port number value for your program.

Not all IP addresses are visible to other parts of the world. In fact, some are reserved for non-public addresses (such as 192.168.y.z or 10. x. y. z ). The address 127.0.0.1 is the local address; it always points to the current computer. The program can use this address to connect other programs running on the same computer.

IP address is not easy to remember, you can spend some money to register a host name or domain name for a specific IP address (for example, use www.bitsCN.com instead of 222.76.216.16 ). The Domain Name Server (DNS) processes the ing of names to IP addresses. Each computer can have a host name even if it is not officially registered.

How much information is transmitted over a network is based on many factors, one of which is the protocol used. Many protocols form a protocol stack based on simple and low-level protocols. For example, the HTTP protocol is used for communication between Web browsers and Web servers. it is based on the TCP protocol, while the TCP protocol is based on the IP protocol.

When sending information between your two programs, you usually choose TCP or UDP. TCP establishes a continuous connection between the two ends, and the information you send is ensured to reach their destination in order. UDP does not establish a connection. it is fast but unreliable. The information you send may not reach the other end; or they do not arrive in order. Sometimes multiple copies of one message reach the receiving end, even if you only send it once.

II. use the address and host name

The socket module provides several functions for using host names and addresses.

Gethostname () returns the host name of the computer where the program is running:

>>> Import socket
>>> Socket. gethostname ()
'Lenovo'

Gethostbyname (name) tries to interpret the given host name as an IP address. First, check whether the current computer can be interpreted. If not, an explanation request will be sent to a remote DNS server (the remote DNS server may also forward the explanation request to another DNS server until the request can be processed ). The gethostbyname function returns this IP address or raises an exception after the search fails.

>>> Socket. gethostbyname ('Lenovo ')
'192. 168.1.4'
>>> Socket. gethostbyname ('www .bitsCN.com ')
'1970. 76.216.16'

An extension is gethostbyname_ex (name), which returns a triple containing three elements, it is the primary host name of the given address, a list of optional host names of the same IP address, a list of other IP addresses of the same interface of the same host (the list may be empty ).

>>> Socket. gethostbyname ('www .163.com ')
'60. 191.81.49'
>>> Socket. gethostbyname_ex ('www .163.com ')
('Www .cache.split.netease.com ', ['www .163.com'], ['60. 191.81.48 ', '60. 191.81.49
, '60. 191.81.50 ', '60. 191.81.51', '60. 191.81.52 ', '60. 191.81.53', '60. 191.81.54
, '192. 181.28.50 ', '192. 181.28.51', '192. 181.28.52 ', '192. 181.28.53', '192. 220.
8.54 ', '192. 181.31.182', '192. 181.31.183 ', '192. 181.31.184'])

The gethostbyaddr (address) function serves the same purpose as gethostbyname_ex, but the parameter you provide to it is an IP address string:

>>> Socket. gethostbyaddr ('192. 165.102.205 ')
('Homepage .vip.cnb.yahoo.com ', ['www .yahoo.com.cn'], ['192. 165.102.205 '])

The getservbyname (service, protocol) function requires a service name (such as 'telnet 'or 'ftp') and a protocol (such as 'tcp 'or 'udp '), return the port number used by the service:

>>> Socket. getservbyname ('http ', 'tcp ')
80
>>> Socket. getservbyname ('telnet ', 'tcp)
23

Generally, non-Python programs store and use IP addresses in a 32-bit byte package. The inet_aton (ip_addr) and inet_ntoa (packed) functions are Converted to IP addresses in this form:

>>> Socket. inet_aton ('2017. 76.216.16 ')
'\ XdeL \ xd8 \ x10'
>>> Socket. inet_ntoa ('\ xdeL \ xd8 \ x10 ')
'1970. 76.216.16'

Socket also defines some variables to represent the reserved IP address. INADDR_ANY and INADDR_BROADCAST are reserved IP addresses that represent any IP addresses and broadcast addresses respectively. INADDR_LOOPBACK represents a loopback device and is always at 127.0.0.1. These variables are in the format of 32-bit bytes.

The getfqdn ([name]) function returns the full domain name about the given host name (if omitted, the full domain name of the local machine is returned ).

3. use low-level socket communication

Although Python provides some encapsulation to make it easier to use socket, you can also directly use socket to work.

1. create and destroy a socket

The socket (family, type [, proto]) function in the socket module creates a new socket object. The value of family is generally AF_INET. The value of type is usually SOCK_STREAM (for targeted connections, reliable TCP connections) or SOCK_DGRAM (for UDP ):

>>> From socket import *
>>> S = socket (AF_INET, SOCK_STREAM)

The family and type parameters imply a protocol, but you can use the third optional parameter of socket (The proto value is IPPROTO_TCP or IPPROTO_RAW) to specify the protocol used. Instead of using the IPPROTO_XX variable, you can use the getprotobyname function:

>>> Getprotobyname ('tcp ')
6
>>> IPPROTO_TCP
6

Fromfd (fd, type [, proto]) is a rarely used function. it is used to create a socket object from an opened file descriptor (the file descriptor consists of the fileno () of the file () ). The file descriptor is connected to a real socket instead of a file. The fileno () method of the socket object returns the file descriptor about this socket.

When you use a socket object, you should call the close () method to explicitly close the socket to release resources as soon as possible (although the socket will be automatically closed when it is recycled by the garbage collector ). In addition, you can use the shutdown (how) method to close one or both sides of the connection. Parameter 0 blocks socket from receiving data, 1 blocks sending, and 2 blocks receiving and sending.

2. connect to the socket

When two sockets are connected (for example, TCP), one end listens to and receives the connection, and the other end initiates the connection. The frontend creates a socket, calls the bind (address) function to bind a specific address and port, calls the listen (backlog) incoming connection, and finally calls accept () to receive this new incoming connection. The following is the code on the server side:

>>> S = socket (AF_INET, SOCK_STREAM)
>>> S. bind ('2017. 0.0.1 ', 127 ))
>>> S. listen (1)
>>> Q, v = s. accept () # return socket q and address v

Note: The above code will remain waiting until the connection is established. Next, open another Python interpreter and use it as the client. then, type the following code:
>>> From socket import *
>>> S = socket (AF_INET, SOCK_STREAM)
>>> S. connect ('127. 0.0.1 ', 127) # initiate a connection

Okay. let's verify whether the connection is established. Enter the following code on the server to send a message:

>>> Q. send ('Hello, I come from pythontik.com ') Note: Sometimes the send () argument 1 must be string or buffer, not str error may occur, the reason may be that your machine does not support the UTF-8 character set. the temporary solution is q. send (B 'hello... ')
31 # Number of bytes sent

Enter the following code on the client to receive information:
>>> S. recv (1024)
'Hello, I come from pythontik.com'

The address you pass to bind and connect is a socket tuples (ipAddress, port) about AF_INET ). Instead of connect, you can call the connect_ex (address) method. If an error is returned for the C connect call, connect_ex returns an error (otherwise, 0 indicates success) instead of an exception.

When you call listen, you give it a parameter. this value indicates the total number of connections allowed to be placed in the waiting queue. When the waiting queue is full, if more connections arrive, the remote end will be notified that the connection is rejected. The SOMAXCONN variable in the socket module indicates the maximum number of waiting queues.

The accept () method returns an address in the form of bind and connect, representing the address of the remote socket. The value of variable v is shown below:

>>> V
('1970. 0.0.1 ', 127)

UDP is an untargeted connection, but you can still use the given destination address and port to Call connect to associate a socket.

3. send and receive data

Send (string [, flags]) sends the given string to the remote socket. Sendto (string [, flags], address) is sent to a specified string to a specific address. Generally, the send method is used for the socket with reliable connection, and the sendto method is used for the socket with unreliable connection. However, if you call connect on a UDP socket to establish a connection with a specific target, in this case, you can use the send method instead of sendto.

Both send and sendto return the actual number of bytes sent. When you send a large amount of data quickly, you may want to ensure that all information has been sent. you can use the following function:

Def safeSend (sock, msg ):
Sent = 0
While msg:
I = sock. send (msg)
If I =-1: # an error occurs.
Return-1
Sent + = I
Msg = msg [I:]
Time. sleep (25)
Return sent

The recv (bufsize [, flags]) method receives an incoming message. If a large amount of data is waiting, it only returns the data of the previous bufsize bytes. Recvfrom (bufsize [, flags]) does the same thing, except that the returned value of AF_INET socket is (data, (ipAddress, port )), this helps you know where the message comes from (this is useful for non-connected sockets ).

The send, sendto, recv, and recvfrom methods both have an optional flags parameter. the default value is 0. You can combine the socket. MSG _ * variable (by bit or) to create the flags value. These values vary by platform, but the most common values are as follows:

MSG_OOB: process out-of-band data (TCP emergency data ).
MSG_DONTROUTE: Route tables are not used; directly sent to interfaces.
MSG_PEEK: return the waiting data and do not delete them from the queue.

For example, if you have an open socket with a message waiting for receiving, you can receive the message without deleting it from the incoming data queue:

>>> Q. recv (1024, MSG_PEEK)
'Hello'
>>> Q. recv (1024, MSG_PEEK) # you can get it again because it is not deleted.
'Hello'

Makefile ([mode [, bufsize]) method returns a File Class object, which encapsulates socket, so that you can pass it to the code that requires the parameter to be a file later (maybe you prefer to use the file method instead of send and recv ). The value of this optional mode and bufsize parameter is the same as that of the built-in open function.

4. use socket options

The getpeername () and getsockname () methods of the socket object return a binary group containing an IP address and port (the form of this binary group is like what you pass to connect and bind ). Getpeername returns the address and port of the connected remote socket, and getsockname returns the same information about the local socket.

By default, the socket is blocked, meaning that the call of the socket method will not return until the task is completed. For example, if the cache for the data stored for sending out is full, you attempt to send more data, then your call to send will be blocked until it can put more data into the cache. You can call the setblocking (flag) method (where the flag value is 0 and setblocking (0) to change this default behavior so that the socket is non-blocking. When the socket is non-blocking, an error exception occurs if the action is performed. The following code attempts to continuously accept new connections and process them using the processRequest function. If a new connection is invalid, it will try again in half a second. Another method is to call select or poll on your listening socket to detect the arrival of a new connection.

Other socket options can be set and obtained using setsockopt (level, name, value) and getsockopt (level, name [, buflen]) methods. Socket represents different layers of a protocol stack. the level parameter specifies the layer to which the option is applied. The level value starts with SOL _ (SOL_SOCKET, SOL_TCP, and so on ). Name indicates which option you are dealing. For value, if this option requires a value, value can only be a numeric value. You can also pass a cache (a string), but you must use the correct format. If you do not specify the buflen parameter for getsockopt, a numeric value is required and this value is returned. If you provide buflen, getsockopt returns a cached string with the maximum length of buflen bytes. In the following example, the cache size of a socket for sending is set to 64 KB:

>>> S = socket (AF_INET, SOCK_STREAM)
>>> S. setsockopt (SOL_SOCKET, SO_SNDBUF, 65535)

You can use the following code to obtain the TTL and number of hops that a packet can have before it is discarded:

>>> S. getsockopt (SOL_IP, IP_TTL)
32

5. numerical conversion

Because the byte sequence of different platforms is different, we use the standard network byte sequence for data transmission over the network. The nthol (x) and ntohs (x) functions require a value in the byte sequence of the network and convert it to the same value in the byte sequence of the current host, while htonl (x) and htons (x) on the contrary:

>>> Import. socket
>>> Socket. htons (20000) # Convert to a 16-bit value
8270
>>> Socket. htonl (20000) # Convert to a 32-bit value
541982720
>>> Socket. ntohl (541982720)
20000

Use SocketServers

The SocketServers module defines a base class for a set of socket services. this class compresses and hides the details of the socket connections that are listened, accepted, and processed.

1. SocketServers family
Both TCPServer and UDPServer are subclasses of SocketServer, which process TCP and UDP information respectively.
Note: SocketServer also provides UnixStreamServer (TCPServer subclass) and UNIXdatagramServer (UDPServer subclass). They all replace AF_INET with AF_UNIX when creating a listening socket.

By default, the socket service processes a connection at a time, but you can use the ThreadingMixIN and ForkingMixIn classes to create the threads and sub-processes of any SocketServer. In fact, the SocketServer module provides some useful classes to solve your troubles. they are ForkingUDPServer, ForkingTCPServer, ThreadingUDPServer, ThreadingTCPServer, ThreadingUnixStreamServer, and threadingunixw.ramserver.

The SocketServer processes incoming connections in the usual way. to make it more useful, you should provide your own request processor class for it to pass a socket for processing. The BaseRequestHandler class in the SocketServer module is the parent class of all request handlers. Suppose, for example, if you need to write a multi-thread email server, you must first create a MailRequestHandler, which is a subclass of BaseRequestHandler and then pass it to a newly created SocketServer:
Import SocketServer
... # Create your MailRequestHandler
Addr = ('1970. 172.20.6 ', 25) # listening address and port
Server = SocketServer. ThreadingTCPServer (addr, MailRequestHandler)
Server. serve_forever ()

Each time a new connection comes, the server creates a new MailRequestHandler instance and calls its handle () method to process the new request. Because the server inherits from ThreadingTCPServer, it starts a separate thread for each new request to process the request, so that multiple requests can be processed simultaneously. If handle_request () is used instead of server_forever, it processes connection requests one by one. Server_forever only calls handle_request repeatedly.

Generally, you only need to use one of the socket services, but if you need to create your own subclass, you can overwrite the methods we mentioned below to customize it.

When a service is created for the first time, the __init _ function calls the server_bind () method to bind the listening socket (self. socket) to the correct address (self. server_address ). Then call server_activate () to activate the service (the listen method of socket is called by default ).

This socket service does not do anything until the handle_request or serve_forever method is called. Handle_request calls get_request () to wait for and receive a new socket connection, and then calls verify_request (request, client_address) to check whether the service will process the connection (you can use this in access control, by default, verify_request always returns true ). If the request is processed, handle_request then calls process_request (request, client_address). if process_request (request, client_address) causes an exception, handle_error (request, client_address) is called ). By default, process_request simply calls finish_request (request, client_address). the sub-process and thread class overwrite this behavior to start a new process or thread and then call finish_request. Finish_request instantiate a new request processor, which calls their handle () method in turn.

When SocketServer creates a new request processor, it passes the self variable of the _ init _ function of the processor so that the processor can access information about the service.

The fileno () method of SocketServer returns the file descriptor of the listening socket. The address_family member variable specifies the socket family (such as AF_INET) of the listening socket. server_address contains the address bound to the listening socket. The socket variable contains the listening socket itself.

2. request processor

The processors include the setup (), handle (), and finish () methods. you can overwrite them to customize your own behaviors. Generally, you only need to override the handle method. The _ init _ function of BaseRequestHandler calls the setup () method for initialization. handle () serves the request and finish () is used for cleaning, if handle or setup causes an exception, finish will not be called. Remember, your request processor will create a new instance for each request.

The request member variable contains the socket recently accepted by the stream (TCP) service. for the datagram service, it is a tuples that contain incoming messages and listening socket. Client_address contains the sender's address. the server has a reference to SocketServer (through which you can access its members, such as server_address ).

The following example implements an EchoRequestHandler, which serves as a server that sends the data sent by the client back to the client:

>>> Import SocketServer
>>> Class EchoRequestHandler (SocketServer. BaseRequestHandler ):
... Def handle (self ):
... Print 'got new connection! '
... While 1:
... Mesg = self. request. recv (1024)
... If not msg:
... Break
... Print 'stored Ed: ', msg
... Self. request. send (msg)
... Print 'done with connection'
>>> Server = SocketServer. ThreadingTCPServer ('2017. 0.0.1 ', 127), EchoReuestHandler)
>>> Server. handle_request () # wait for connection after execution
Got new connection!
Received: Hello!
Received: I like Tuesdays!
Done with connection

Open another Python interpreter as the client and execute the following code:

>>> From socket import *
>>> S = socket (AF_INET, SOCK_STREAM)
>>> S. connect ('2017. 0.0.1 ', 120 ))
>>> S. send ('Hello! ')
6
>>> Print s. recvs (1024)
Hello!
>>> S. send ('I like Tuesdays! ')
16
>>> Print s. recvs (1024)
I like Tuesdays!
>>> S. close ()

The SocketServer module also defines two sub-classes of BaseRequestHandler: StreamRequestHandler and DatagramRequestHandler. They overwrite the setup and finish methods and create two file objects rfile and wfile. you can use these two file objects to read and write data to the client, instead of using the socket method.

Socket blocking or synchronous programming


I. use socket

The most basic part of network programming is socket ). There are two types of sockets: server socket and client socket. After you create a server socket, tell it to wait for the connection. Then it listens to a network address (for example, xxx. xxx: xxx) until the client connects. Then the two ends can communicate with each other.

Processing client socket is usually easier than processing server socket, because the server must always be prepared to process connections from the client, and it must process multiple connections, while the client only needs simple connections, then do something and disconnect.

To implement a socket, you can specify three parameters: Address Series (socket by default. AF_INET), stream socket (this is a default value: socket. SOCK_STREAM) or Datagram socket (socket. SOCK_DGRAM), protocol (default value is 0 ). For a simple socket, you can use the default value without specifying any parameters.

After using the bind method, the server socket calls the listen method to listen to a given address. Then, the client socket can connect to the server by using the connect method (the address parameter used by the connect method is the same as that of the bind. The listen method requires a parameter, which is the number of connections that can be contained in the connection queue.

Once the server socket calls the listen method, it enters the listening state. then, an infinite loop is often used: 1. the connection at the room end is accepted, which is achieved by calling the accept method. After this method is called, it will be in the blocking status (waiting for the client to initiate a connection) until a client connects. after the connection, accept returns a tuple in the form of (client, address, specifically, the client is a socket used to communicate with the client, and the address is the client in the form of xxx. xxx. xxx. xxx: xxx address; 2. The server then processes client requests; 3. Call 1 after processing is complete.

There are two methods for data transmission: send and recv. Send uses the string parameter to send data. the recv parameter is the number of bytes, indicating the amount of data received at a time. if you are not sure about the amount of data to be received at a time, you 'd better use 1024.

The following is an example of the smallest server/client:

Server:

Import socket
S = socket. socket ()
Host = socket. gethostname ()
Port = 1234
S. bind (host, port ))
S. listen (5)
While True:
C, addr = s. accept ()
Print 'got connection from', addr
C. send ('thank you for connection ')
C. close ()

Client:

Import socket
S = socket. socket ()
Host = socket. gethostname ()
Port = 1234
S. connect (host, port ))
Print s. recv (1024)

Note: If you use Ctrl-C to stop the server, it may take a while to use the same port again.

II. use SocketServer

The SocketServer module simplifies the compilation of network servers.
It provides four basic services: TCPServer (using TCP protocol), UDPServer (using datagram), UnixStreamServer,

Unix‑ramserver. UnixStreamServer and unixw.ramserver are used for Unix-like platforms.
These four types of processing requests use synchronous methods, that is, the current request processing must be completed before the next request processing starts.

.

Four steps are required to create a server using SocketServer:

1. create a request processor class using the subclass BaseRequestHandler class and the handle () method that overwrites it.

Request;
2. instantiate the service class such as TCPServer and pass the parameter to it: server address and request processor class;
3. call the handle_request () or serve_forever () method of the service instance object to process the request.

The following uses SocketServer to write the simplest server in synchronous mode:

From SocketServer import TCPServer, StreamRequestHandler
# Step 1. The StreamRequestHandler class is a subclass of the BaseRequestHandler class, which defines
# Rfile and wfile methods
Class Handler (StreamRequestHandler ):
Def handle (self ):
Addr = self. request. getpeername ()
Print 'got connection from', addr
Self. wfile. write ('thank you for connection ')

# Step 2. ''Indicates the host of the running server.
Server = TCPServer ('', 1234), Handler)
# Step 3. Serve_forever () leads to loop
Server. serve_forever ()

Note: You can only connect to one client at a time using the blocking or synchronization method. after the processing is complete, you can connect to the next client.

Non-blocking or asynchronous programming

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.