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
'  # 服务器发送消息的头部需要换行,用

            data_body += '
'   # 头部和body需要空一行
            data_body += '<h1>not found</h1>'   # 服务器没找到浏览器需要的资源,返回的html页面
            new_socket.send(data_body.encode('utf-8'))  # 发送给浏览器
        else:
            data_head = 'HTTP 200 OK/1.1
'  # 请求成功,服务器返回200
            data_head += '
'
            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
'
                        data_body += '
'
                        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
'
                        data_head += 'Content-Length:%d
' % len(data_body)
                        data_head += '
'
                        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()
原文地址:https://www.cnblogs.com/lz-tester/p/9415906.html