1. HTTP服务器的实现

实现一个http服务器说白了就是实现一个监听程序,当客户端发来对应的http请求时,能够解析请求,并且返回对应的资源给客户端,客户端解析显示到浏览器上。这里我使用python实现一个最简单的http服务器。

1.1初始化

定义一个初始化方法,创建套接字,绑定地址,监听端口,cnt用来统计客户端请求数量。

def init(self):
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.bind(("",80))
        self.server_socket.listen(100)
        self.cnt = 0

1.2 启动服务

def start(self):
        # print("cnt = %d"%self.cnt)
        # 主进程阻塞,等待客户端发送请求
        client_socket, client_address = self.server_socket.accept()
        self.cnt += 1
        print("connected from[%s, %s]" % client_address)
        # 主进程启动一个子进程处理客户端请求
        start_client_process = Process(target=self.client_server, args=(client_socket,client_address))
        start_client_process.start()
        # 关闭主进程的套接字
        client_socket.close()

1.3 请求处理函数

子进程处理请求,这里为了简化,仅仅区分了请求png文件和其他文件。

    def client_server(self,client_socket, client_addr):
        request_data = client_socket.recv(1024)
        # 打印日志
        self.log(request_data)
        # 构造响应数据
        response_start_line = "HTTP/1.1 200 OK\r\n"
        response_headers = "Server: My server\r\n"
        # 如果请求png图片,那么发送本地的一张图片给客户端
        if request_data.decode().find("1.png") > 0:
            filename = "1.png"
            with open(filename, 'rb+') as f:
                body = f.read()
                f.close()
            client_socket.send(body) 
        # 其他请求,发送一个html文件给客户端
        else:
            filename = "1.html"
            with open(filename, encoding='utf-8') as f:
                body = f.read()
                f.close()
            response = response_start_line + response_headers +"\r\n" + body 
            client_socket.send(bytes(response,"utf-8")) 
        client_socket.close()

1.4 打印日志

加了一个日志打印方法,记录请求的时间和内容

 def log(self, data):
        now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        with open("log.txt",'a+') as f:
            # f.write(now_time)
            f.write("\n%s\n%s" %(now_time, data))

完整的代码如下:

import socket
import datetime
from multiprocessing import Process
class webserver:
    def init(self):
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.bind(("",80))
        self.server_socket.listen(100)
        self.cnt = 0
    def start(self):
        print("cnt = %d"%self.cnt)
        client_socket, client_address = self.server_socket.accept()
        self.cnt += 1
        print("connected from[%s, %s]" % client_address)
        start_client_process = Process(target=self.client_server, args=(client_socket,client_address))
        start_client_process.start()
        client_socket.close()
    def client_server(self,client_socket, client_addr):
        request_data = client_socket.recv(1024)
        # 打印日志
        self.log(request_data)
        # 构造响应数据
        response_start_line = "HTTP/1.1 200 OK\r\n"
        response_headers = "Server: My server\r\n"
        if request_data.decode().find("1.png") > 0:
            filename = "1.png"
            with open(filename, 'rb+') as f:
                body = f.read()
                f.close()
            client_socket.send(body) 
        else:
            filename = "1.html"
            with open(filename, encoding='utf-8') as f:
                body = f.read()
                f.close()
            response = response_start_line + response_headers +"\r\n" + body 
            client_socket.send(bytes(response,"utf-8"))    
        client_socket.close()
    def main(self):
        self.init()
        while True:
            self.start()
    def log(self, data):
        now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        with open("log.txt",'a+') as f:
            f.write("\n%s\n%s" %(now_time, data))

if __name__ == '__main__':
    res = webserver()
    res.main()

2. 执行结果

运行程序,然后打开浏览器,在浏览器中输入127.0.0.1,就可以看到输出结果。如果打开chrome的network,可以看到浏览器发送了三个请求。

打开errlog可以看到,有三条浏览记录