Concurrent Server, HTTP Protocol for python Network Programming

Keywords: Programming socket Python network

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]))

Posted by peter_anderson on Sun, 27 Jan 2019 23:06:14 -0800