web服務-2、四種方法實現並發服務器-多線程,多進程,協程,(單進程-單線程-非堵塞)


知識點:1、使用多線程,多進程,協程完成web並發服務器 2、單進程-單線程-非堵塞也可以實現並發服務器

1、多進程和協程的代碼在下面注釋掉的部分,我把三種寫在一起了

import socket
import re
import threading
import multiprocessing
import gevent

"""服務器收發數據"""
def web_server(new_socket):

        datas = new_socket.recv(1024).decode('utf-8')  # 接收瀏覽器請求的數據
        print(datas)
        data1 = datas.splitlines()
        res = re.match("[^/]+(/[^ ]*)", data1[0])  # 使用正則獲取到請求頭部中的的第一行中的請求地址對象
        if res:  # 判斷如果請求地址有內容
            file_name = res.group(1)   # 獲取正則對象中的內容
            if file_name == '/':   # 如果地址是‘/’,也就是請求地址后面沒有帶指的頁面,即主頁
                file_name = '/index.html'
        try:
            data = open('./html'+file_name,'rb')   # 獲取請求的資源在服務器中的文件
        except:
            data_body = 'HTTP 404 NOT FOUND/1.1\r\n'  # 服務器發送消息的頭部需要換行,用\r\n
            data_body += '\r\n'   # 頭部和body需要空一行
            data_body += '<h1>not found</h1>'   # 服務器沒找到瀏覽器需要的資源,返回的html頁面
            new_socket.send(data_body.encode('utf-8'))  # 發送給瀏覽器
        else:
            data_head = 'HTTP 200 OK/1.1\r\n'  # 請求成功,服務器返回200
            data_head += '\r\n'
            data_body = data.read()
            data.close()   # 關閉文件
            new_socket.send(data_head.encode('utf-8'))
            new_socket.send(data_body)
        new_socket.close()  # 關閉新的客戶端套接字

"""主程序入口""" def main(): tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 創建套接字 tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 防止下一次使用該服務器端口被占用情況 tcp_socket.bind(('127.0.0.1', 7789)) # 服務器綁定地址和端口 tcp_socket.listen(128) # 監聽套接字 while True: new_socket, adrees = tcp_socket.accept() # 1、多進程實現並發服務 # p = multiprocessing.Process(target=web_server, args=(new_socket,)) # p.start() # 2、協程實現並發服務 # p = gevent.spawn(web_server, new_socket) # p.start() # 3、多線程實現並發服務 t = threading.Thread(target=web_server, args=(new_socket,)) t.start() t.join() new_socket.close() tcp_socket.close() # 關閉監聽套接字
if __name__ == '__main__':
main()
運行效果:
瀏覽器訪問本地,會顯示一個界面,而且可以開多個瀏覽器一起運行

2、單進程-單線程-非堵塞也可以實現並發服務器

"""利用單進程-單線程-非堵塞也可以實現web並發服務(即不用多線程,多進程,協程)
   思路:1、設置套接字為非堵塞
         2、在接收客戶端處:因為是非堵塞,所以要捕捉異常,當有客戶端進來,新客戶端的套接字也要設置非堵塞
           還需要判斷接recv是否是有數據,沒有數據說明客戶端斷開連接,關閉套接字
          
"""


def main():
    main_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    main_socket.bind(('127.0.0.1',7785))
    main_socket.listen(128)
    main_socket.setblocking(False)
    socket_list = list()
    while True:
        time.sleep(1)
        try:
            new_socket,new_adress = main_socket.accept()
        except:
            print('沒有客戶端進來,請稍等.....')
        else:
            print('一個新的客戶端進來了......')
            new_socket.setblocking(False)
            socket_list.append(new_socket)
        for client in socket_list:
            try:
                recv_data = client.recv(1024).decode('utf-8')
            except:
                print('客戶端沒有發送過來數據')
            else:
                print('無異常')
                if recv_data:
                    print('客戶端發來了消息')
                    print(recv_data)
                    data1 = recv_data.splitlines()
                    res = re.match("[^/]+(/[^ ]*)", data1[0])
                    if res:
                        file_name = res.group(1)
                        print('--------------' + res.group(1))
                        if file_name == '/':
                            file_name = '/index.html'
                    try:
                        data = open('./html' + file_name, 'rb')
                    except:
                        data_body = 'HTTP 404 NOT FOUND/1.1\r\n'
                        data_body += '\r\n'
                        data_body += '<h1>not found</h1>'
                        client.send(data_body.encode('utf-8'))
                    else:
                        data_body = data.read()
                        data.close()
                        data_head = 'HTTP 200 OK/1.1\r\n'
                        data_head += 'Content-Length:%d\r\n' % len(data_body)
                        data_head += '\r\n'
                        reponse = (data_head.encode('utf-8')+data_body)
                        client.send(reponse)
                else:
                    client.close()
                    socket_list.remove(client)
    main_socket.close()


if __name__ == '__main__':
    main()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM