Python实现Web服务器——并发服务器(1)

主要使用了socket库

1.显示固定的页面

import socket


def client_server(client_socket):
    recv_data = client_socket.recv(1024).decode('utf-8')
    recv_info = recv_data.splitlines()
    for i in recv_info:
        print(i)
    reply_head = 'HTTP/1.1 200 OK \r\n'
    reply_head += '\r\n'
    reply_body = 'Hello world!'
    client_socket.send((reply_head + reply_body).encode('utf-8'))
    client_socket.close()


def main():
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.bind(("", 7789))
    server.listen(128)
    while True:
        client_socket, client_addr = server.accept()
        client_server(client_socket)


if __name__ == '__main__':
    main()

运行之后就在本地建立起了一个TCP服务端,可以使用浏览器访问本地的网址看到Hello world!内容,同时服务端会打印信息

2.页面访问

import socket
import re


def client_server(client_socket):
    # 打印信息
    recv_data = client_socket.recv(1024).decode('utf-8', errors='ignore')
    data_info = recv_data.splitlines()
    for i in data_info:
        print(i)
    # 获取输入的信息(地址)
    target = data_info[0]
    target_file = re.match('[^/]+(/[^ ]*)', target).group(1)
    print("file name is " + target_file)

    if target_file is '/':
        location = DOCUMENTS_ROOT + '/index.html'
    else:
        location = DOCUMENTS_ROOT + target_file

    try:
        f = open(location, 'rb')
    except IOError:
        reply_head = 'HTTP/1.1 404 not found\r\n'
        reply_head += '\r\n'
        reply_body = b'not found'
    else:
        reply_head = 'HTTP/1.1 200 OK \r\n'
        reply_head += '\r\n'
        reply_body = f.read()
        f.close()
    finally:
        # 先返回head
        client_socket.send(reply_head.encode('utf-8'))
        # 再返回body
        client_socket.send(reply_body)
        client_socket.close()


def main():
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.bind(("", 7788))
    server.listen(128)
    while True:
        client_socket, client_addr = server.accept()
        client_server(client_socket)


DOCUMENTS_ROOT = './html'

if __name__ == '__main__':
    main()


这样就可以访问根目录中html文件夹下面的内容,例如:(提前保存了一个百度网页)

3.使用多进程

import socket
from multiprocessing import Process
from 页面访问 import client_server


DOCUMENTS_ROOT = './html'
SERVER_ADDR = (ADDR, PORT) = ("", 7788)


class WebServer():
    def __init__(self, addr):
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server.bind(addr)
        self.server.listen(128)

    def run_last(self):
        while True:
            client_socket, client_port = self.server.accept()
            print("address:" + str(client_port) + "connected")
            p = Process(target=self.client((client_socket)))
            p.start()
            # 因为已经将socket复制到了另一个子线程中,因此主线程的socket可以关闭
            client_socket.close()

    def client(self, client_socket):
        client_server(client_socket)


def main():
    http_server = WebServer(SERVER_ADDR)
    print("Server start on port:" + str(PORT))
    http_server.run_last()


if __name__ == '__main__':
    main()


client部分直接继承第二个部分,多进程保证了可以同时处理多个网页请求

解决了一个问题:只打开主页的时候什么都不输入会数组空长报错,于是引入了try报错机制,使用except解决了不输入具体目录的问题

4.使用多线程实现

import socket
from threading import Thread
from 显示内容 import client_server


DOCUMENTS_ROOT = './html'
SERVER_ADDR = (ADDR, PORT) = ("", 7788)


class WebServer():

    def __init__(self, addr):
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server.bind(addr)
        # 转变为监听状态
        self.server.listen(128)

    def run_last(self):
        while True:
            clinet_socket, client_port = self.server.accept()
            t = Thread(target=self.client(clinet_socket))
            print('address:' + str(client_port) + ' connected')
            t.start()
            clinet_socket.close()

    def client(self, client_socket):
        client_server(client_socket)


def main():
    http_server = WebServer(SERVER_ADDR)
    print("Server is start on port:" + str(PORT))
    http_server.run_last()


if __name__ == '__main__':
    main()

解决了一个问题:
使用多线程实现的时候,浏览器在刷新的时候会报错,会显示软件中断了连接,这里需要在显示页面部分中添加报错机制

        try:
            # 先返回head
            client_socket.send(reply_head.encode('utf-8'))
            # 再返回body
            client_socket.send(reply_body)
            client_socket.close()
        except ConnectionAbortedError:
            pass

https://bbs.csdn.net/topics/392188437

即可解决问题

猜你喜欢

转载自blog.csdn.net/weixin_43826242/article/details/87869784