Concurrent Server, HTTP Protocol for python Network Programming
This document is only used for learning notes. Please indicate where it came from when it was reproduced.
Single process server
- Complete a simple TCP server
Case v11:
''' //Complete a simple TCP server //Single process server ''' from socket import * serSocket = socket(AF_INET,SOCK_STREAM) #Reuse binding information serSocket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) localAddr = ('',7788) serSocket.bind(localAddr) serSocket.listen(5) while True: print('--------Host process: waiting for the client to arrive--------') newSocket,destAddr = serSocket.accept() print('--------Main process: responsible for data processing--------') try: while True: recvData = newSocket.recv(1024) if len(recvData) > 0 : print('recv[{}]:{}'.format(str(destAddr),recvData)) else: print('[{}]Client has been shut down'.format(str(destAddr))) break finally: newSocket.close() serSocket.close()
This server:
- Only one customer can be served at the same time, and Boone serves multiple customers at the same time.
- Similar to finding a star signature, a client needs to wait patiently to get a service when the server serves for a client, while another client initiates a connection. As long as the queue of the server listen has an idle location, it will connect for the new client, and the client can send data, but when the server serves for the new client, it can. Can receive all data at one time.
- When recv receives data, the return value is empty, that is, no data is returned, which means that the client has called close to shut down; therefore, the server judges whether the client has been offline by judging whether recv receives data is empty or not.
Multiprocess Server
''' //Multiprocess Server ''' from socket import * from multiprocessing import * from time import sleep #Processing and serving client requests def dealWithClient(newSocket,destAddr): while True: recvData = newSocket.recv(1024) if len(recvData) > 0: print('recv[{}]:{}'.format(str(destAddr), recvData)) else: print('[{}]Client has been shut down'.format(str(destAddr))) break newSocket.close() #Main function def main(): # Create Server Socket serSocket = socket(AF_INET, SOCK_STREAM) # Reuse binding information serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) localAddr = ('', 7788) serSocket.bind(localAddr) serSocket.listen(5) try: while True: print('--------Host process: waiting for the client to arrive--------') newSocket, destAddr = serSocket.accept() print('--------process x: Responsible for data processing--------') client = Process(target=dealWithClient,args=(newSocket,destAddr)) client.start() newSocket.close() finally: serSocket.close() if __name__ == '__main__': main()
Multithread Server
''' //Multithread Server ''' from socket import * from threading import Thread from time import sleep #Processing and serving client requests def dealWithClient(newSocket,destAddr): while True: recvData = newSocket.recv(1024) if len(recvData) > 0: print('recv[{}]:{}'.format(str(destAddr), recvData)) else: print('[{}]Client has been shut down'.format(str(destAddr))) break newSocket.close() def main(): serSocket = socket(AF_INET, SOCK_STREAM) # Reuse binding information serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) localAddr = ('', 7788) serSocket.bind(localAddr) serSocket.listen(5) try: while True: print('--------Host process: waiting for the client to arrive--------') newSocket, destAddr = serSocket.accept() print('--------thread x: Responsible for data processing--------') client = Thread(target=dealWithClient,args=(newSocket,destAddr)) client.start() finally: serSocket.close() if __name__ == '__main__': main()
Single process-non-blocking server
- Reasons for multi-process and multi-threading: If there is no multi-threaded and multi-process, then the task is single-task, that is, when serving one customer, it can not serve other customers at the same time.
''' //Create a single process non-blocking server ''' from socket import * serSocket = socket(AF_INET,SOCK_STREAM) localAddr = ('',7790) serSocket.bind(localAddr) #Make socket s non-blocking serSocket.setblocking(False) #Set to passive socket serSocket.listen(5) #Used to save all linked client information clientAddrList = [] while True: #Waiting for a new client to arrive (that is, the client that completes three handshakes) try: clientSocket, clientAddr = serSocket.accept() except: pass else: print("A new client arrives:{}".format(str(clientAddr))) clientSocket.setblocking(False) clientAddrList.append(( clientSocket, clientAddr)) #Processing data for clientSocket,clientAddr in clientAddrList: try: recvData = clientSocket.recv(1024) except: pass else: #Data Processing If the length of the data received is greater than 0, then output, if less than 0, disconnect if len(recvData) > 0: print("[{}]:{}".format(str(clientAddr),recvData)) else: clientSocket.close() clientAddrList.remove((clientSocket,clientAddr)) print("[{}]Offline".format(str(clientAddr)))
select Edition - TCP Single Process Server
- select principle
- selet can detect some sockets. Returns the socket that receives information from the socket list.
- selet is more efficient than single-process-non-blocking servers.
- selct echo server
''' select Echo Server ''' import socket import select import sys server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind(('',7789)) server.listen(5) inputs = [server,] running = True while True: #Call the select function to block waiting # List of sockets acceptable to readable # A list of sockets that writeable can send # List of sockets acceptable to readable readable,writeable,exceptinal = select.select(inputs,[],[]) #All three parameters are lists #The first is to check if sockets in the list are not receivable. #The second is to check whether sockets in the list are not available for data. #The third is to detect whether sockets in the list produce some exceptions #Data arrival cycle for sock in readable: #Listen for new connections if sock == server: conn,addr = server.accept() #socket select ed to listen on inputs.append(conn) #Listen for keyboard input #elif sock == sys.stdin: # cmd = sys.stdin.readline() # running = False # break #Data arrival else: #Read the data sent by the customer service connection data =sock.recv(1024) if data: sock.send(data) else: # Remove the socket that select listens on inputs.remove(sock) sock.close() if not running: break server.close()
- select is currently available on almost all platforms.
- The disadvantage is that:
- There is a maximum limit to the number of file descriptors that a single process can monitor.
- Scanning socket s is sequential, that is, polling, which is inefficient.
- Sockets are very busy. select() completes the scheduling by traversing the FD_SETSIZE Socket, regardless of which Socket is active, traversing it once. It wastes a lot of cpu time.
epoll version - TCP single process server
- select: up to 1024, polling mode
- poll: Solves the problem of socket upper limit, polling method
- epoll: No 1024 restrictions, event notification mechanism (non-polling)
''' epoll The server ''' import socket import select s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) s.bind(('',7788)) s.listen(5) epoll = select.epoll epoll.register(s.fileno(),select.EPOLLIN|select.EPOLLET) connecyions = {} addresses = {} while True: epoll_list = epoll.poll() for fd,exents in epoll_list: if fd == s.fileno(): conn,addr = s.accept() print("There's a new customer service arrival.{}".format(str(addr))) connecyions[comm.fileno()] = coon addresses[comm.fileno()] = addr epoll.register(conn.fileno(),select.EPOLLIN|select.EPOLLET) elif events == select.EPOLLIN: recvData = commections[fd].recv(1024) if recvData: print("recv:{}".format(recvData)) else: epoll.unregister(fd) connecyions[fd].close() print("[{}]Client disconnects".format(addresses[fd]))