Socket programming Steps
The server creates a socket, binds the address and port, and listens for incoming connections on the port, and receives the incoming connection through the Accept function once the connection comes in.
The client is also creating a socket. Bind the remote address and port, and then establish the connection to send the data.
Service-side sockets
The following is an example code to detail the service-side socker_server.py
Import Socketimport syshost = "127.0.0.1" PORT = 10000 s = nonefor res in socket.getaddrinfo (HOST, port, socket. Af_unspec, socket. Sock_stream, 0, socket. ai_passive): af, Socktype, Proto, canonname, sa = res try: s = Socket.socket (AF, Socktype, proto) except Socket.error as msg: s = None continue try: s.bind (SA) S.listen (5) except Socket.error as Msg: s.close () s = none continue Breakif S is none: print ' could not open socket ' Sys.exit (1) conn, addr = s.accept () print ' Connected by ', Addrwhile 1: data = CONN.RECV (1024x768) if not data:break
conn.send (data) conn.close ()
First we convert the host/port into a sequence of 5 tuples with the Socket.getaddrinnfo function. This 5-tuple contains all the necessary parameters that we need to create a socket connection. The returned 5 tuples were (family, sockettype, Proto, Canonname, sockaddr)
Family address cluster, with the first parameter of the socket () function. Mainly has the following several
Socket.af_unix communication with processes under a single machine
Socket.af_inet communicates with the server, usually using this.
SOCKET.AF_INET6 Support IPV6
The SocketType socket type, used with the second parameter of the socket () function, is commonly used to have
Socket. Sock_stream default, for TCP protocol
Socket. Sock_dgram for UDP protocol
The proto protocol, which is used for the third parameter of the socket () function. The Getaddrinnfo function returns the appropriate protocol based on the address format and socket type.
Canonname a normalized host name.
SOCKADDR describes a socket address. is a two-tuple, mainly used for bind () and connect () functions
Next, create a socket object, passing in the Af,sockettype,proto returned by the Getaddrinnfo function.
s = Socket.socket (AF, Socktype, Proto)
And then bind my socket address.
S.bind (SA)
Turn on listening mode
S.listen (5)
The Listen function listens for connections to the socket, and the parameter indicates the maximum number of connection queues that the system can suspend before rejecting the connection is 5. These connections have not yet been handled by the accept. The number cannot be infinitely large, usually specifying 5.
Once we hear the connection, we call the Accept function to receive the connection
conn, addr = S.accept ()
The Accept function returns a two-tuple, Conn is a new socket object that is used to receive and send data. Addr represents the socket address on the other end.
Next, we can send and receive data using the Conn object.
data = CONN.RECV (1024) # received, specifying a maximum number of characters to be received at a time of conn.send (data) # Send
Here we receive a connection socket will stop running, so if you want to loop the connection, the accept function into a dead loop.
Client socket
Client socket programming is relatively straightforward, and once connected through connect and the server, you can communicate with each other. socket_client.py as follows
For res in Socket.getaddrinfo (HOST, PORT, Socket.af_unspec, socket. SOCK_STREAM): af, Socktype, Proto, canonname, sa = res try: s = Socket.socket (AF, Socktype, Proto) Except Socket.error as msg: s = None continue try: s.connect (SA) except Socket.error as msg: S.close () s = none continue Breakif S is none: print ' could not open socket ' sys.exit (1) S.sendall (' Hello, world ') data = S.RECV (1024x768) s.close () print ' Received ', repr (data)
The above is mainly for the TCP stream data socket programming. For UDP protocol data, processing is slightly different. For example, the Send receive UDP packet handler function is:
Socket.sendto (String, flags, address) Socket.recvfrom (bufsize[, Flags]) #返回 (string, address), string is the data returned, Address is the sender's socket
Socketserver Module
In Python network programming in addition to the socket module also provides the Socketserver module, this module is the socket module is encapsulated, the socket object creation, binding, connection, receive, send, close are encapsulated in the inside, greatly simplifying the network service programming.
This module provides the following 2 main network service classes for creating the appropriate socket stream
TCPServer creating a socket stream for the TCP protocol
Udpserver creating a socket stream for the UDP protocol
We have a socket stream object and a request processing class is required. The Socketserver module provides the request processing class with Baserequesthandler, as well as its derived classes Streamrequesthandler and Datagramrequesthandler. So as long as you inherit one of these 3 classes, and then override the handle function, this function will be used to process the received request. Let's look at a server-side code sample
import socketserverclass mytcphandler (Socketserver.streamrequesthandler) : "" Creates the request processing class, overriding the handle method. It is also possible to rewrite setup () and finish () to do some work before and after processing "" "Def handle (self): # self.request are the TCP socket connected to the Client Self.data = SELF.REQUEST.RECV (1024x768). Strip () print "{} wrote:". Format (Self.client_address[0]) Print Self.data # Just send back the same data, but upper-cased Self.request.sendall (Self.data.upper ()) if __ name__ = = "__main__": HOST, Port = "localhost", 10000 server = Socketserver.tcpserver ((HOST, PORT), Mytcphandler) # Activate the server; This would keep running until you # interrupt the program with CTRL-C # Server.shutdown () Server.serve_forever () # always loop receive request # Server.handle_request () # exit If only one request is processed
The
looks at whether the code is much simpler, and the Socketserver module uses Multiplexing IO technology to achieve better connection performance. The source code of the Serve_forever function is used in the Select module. by calling Select.select () on the incoming socket object to listen for the file descriptor of the socket object, the application is notified of the appropriate read and write operations once the socket object is found to be ready. The source code is as follows:
def serve_forever (Self, poll_interval=0.5): "" "Handle one request at a Tim e until shutdown. Polls for shutdown every poll_interval seconds. Ignores Self.timeout. If you need to does periodic tasks, do them in another thread. "" "Self.__is_shut_down.clear () Try:while not self.__shutdown_request: # Xxx:con Sider using another file descriptor or # Connecting to the socket to wake this up instead of # polling. Polling reduces our responsiveness to a # shutdown request and wastes CPUs at all other times. R, W, E = _eintr_retry (Select.select, [self], [], [], Poll_interval) If self in r:self._handle_request_noblock () Finally:self.__shutdown_request = Fa LSE Self.__is_shut_down.set ()
Even with select technology, the Tcpserver,udpserver processing request is still synchronous, meaning that a request is processed before the next request can be processed. However, the Socketserver module provides another 2 classes to support asynchronous mode.
Forkingmixin using multiple processes to implement asynchronous
ThreadingMixIn using multithreading for asynchronous
Look at the name to know that the mixin mode is used. The mixin mode can be implemented by multiple inheritance, so the asynchronous mode can be implemented by multiple inheritance of the Network service class.
Class Threadedtcpserver (Socketserver.threadingmixin, socketserver.tcpserver): Pass
For threadindmixin, the principle of implementing asynchrony is to create a thread internally for each request to process. See source
def process_request (self, request, client_address): "" " Start a new thread to process the request. " " t = Threading. Thread (target = Self.process_request_thread, args = (request, client_address)) T.daemon = Self.daemon_threads T.start ()
An example of an asynchronous pattern is provided below
Import Socketimport threadingimport socketserverclass Threadedtcprequesthandler (socketserver.baserequesthandler): def handle (self): data = Self.request.recv (1024x768) Cur_thread = Threading.current_thread () response = " {}: {} ". Format (cur_thread.name, data) Self.request.sendall (response) class Threadedtcpserver (socketserver.threading MixIn, Socketserver.tcpserver): Passdef Client (IP, port, message): sock = Socket.socket (socket.af_inet, socket. Sock_stream) sock.connect ((IP, Port)) Try:sock.sendall (message) response = SOCK.RECV (1024x768) PRI NT "Received: {}". Format (response) Finally:sock.close () if __name__ = = "__main__": # Port 0 means to select a n arbitrary unused port HOST, port = "localhost", 0 server = Threadedtcpserver (HOST, Port), Threadedtcprequesthandl ER) IP, port = server.server_address # Start a thread with the server--that thread would then Start one # more T Hread for each request server_thRead = Threading. Thread (target=server.serve_forever) # Exit The server thread when the main thread terminates Server_thread.daemon = True Server_thread.start () print "server loop running in thread:", server_thread.name Client (IP, port, "Hello Wor LD 1 ") Client (IP, port," Hello World 2 ") the client (IP, port," Hello World 3 ") Server.shutdown () Server.server_clo SE ()
The above is my understanding of the socket, what is wrong or error, please also point out.