使用 python socket 向http服务器发送请求并制作http服务器

发布于:2022-12-22 ⋅ 阅读:(445) ⋅ 点赞:(0)

目录

一、向http服务器发送请求

二、制作http服务器

 2.1 返回固定字符串内容

 2.2 返回固定页面

2.3 返回指定的页面


一、向http服务器发送请求

import socket

# 1.创建套接字
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 2.建立连接
tcp_client_socket.connect(("www.icoderi.com", 80))

# 3.拼接请求协议
# 3.1 请求行
request_line = "GET / HTTP/1.1\r\n"

# 3.2 请求头
request_header = "Host:www.icoderi.com\r\n"

# 3.3 请求空行
request_blank = "\r\n"

# 整体拼接
request_data = request_line + request_header + request_blank

# 4.发送请求协议
tcp_client_socket.send(request_data.encode())

# 5.接收服务器响应
recv_data = tcp_client_socket.recv(4096)
recv_text = recv_data.decode()

# 找到响应数据中的html内容
loc = recv_text.find("<html>")
html_data = recv_text[loc:]
print(html_data)

# 关闭连接
tcp_client_socket.close()

打印结果:

二、制作http服务器

 2.1 返回固定字符串内容

import socket


def request_handler(new_client_socket, ip_port):
    """接收信息,并且做出响应"""

    # 接收客户端浏览器发送的请求协议
    request_data = new_client_socket.recv(1024)  # 接收请求报文

    # 判断协议是否为空
    if not request_data:
        print("%s客户端已下线!" % str(ip_port))
        new_client_socket.close()
    else:
        # 响应行
        response_line = "HTTP/1.1 200 OK\r\n"

        # 响应头
        response_header = "Server:Python20WS/2.1\r\n"

        # 响应空行
        response_blank = "\r\n"

        # 响应主体
        response_body = "Hello World"

        # 拼接响应报文
        response_data = response_line + response_header + response_blank + response_body

        # 发送响应报文
        new_client_socket.send((response_data.encode()))

        # 关闭连接
        new_client_socket.close()

def main():
    """主函数"""

    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 设置地址重用  SOL_SOCKET表示当前套接字,SO_REUSEADDR表示设置地址重用
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

    # 绑定端口
    tcp_server_socket.bind(("", 8080))

    # 设置监听,让套接字由主动变为被动接收
    tcp_server_socket.listen(128)
    
    # 接收客户端连接  定义函数
    new_client_socket, ip_port = tcp_server_socket.accept()

    # 接收请求并作出响应
    request_handler(new_client_socket, ip_port)

if __name__ == '__main__':
    main()

结果:

在浏览器中搜索http://127.0.0.1:8080

但是当前的服务器只能接收一个客户端的一次请求,如果想接收多个客户端的多个请求就需要用到循环和多线程:

import socket
from threading import Thread


def request_handler(new_client_socket, ip_port):
    """接收信息,并且做出响应"""

    # 接收客户端浏览器发送的请求协议
    request_data = new_client_socket.recv(1024)  # 接收请求报文
    print(request_data)

    # 判断协议是否为空
    if not request_data:
        print("%s客户端已下线!" % str(ip_port))
        new_client_socket.close()
    else:
        # 响应行
        response_line = "HTTP/1.1 200 OK\r\n"

        # 响应头
        response_header = "Server:Python20WS/2.1\r\n"

        # 响应空行
        response_blank = "\r\n"

        # 响应主体
        response_body = "Hello World"

        # 拼接响应报文
        response_data = response_line + response_header + response_blank + response_body

        # 发送响应报文
        new_client_socket.send((response_data.encode()))

        # 关闭连接
        new_client_socket.close()

def main():
    """主函数"""

    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 设置地址重用  SOL_SOCKET表示当前套接字,SO_REUSEADDR表示设置地址重用
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

    # 绑定端口
    tcp_server_socket.bind(("", 8080))

    # 设置监听,让套接字由主动变为被动接收
    tcp_server_socket.listen(128)

    while True:
        # 接收客户端连接  定义函数
        new_client_socket, ip_port = tcp_server_socket.accept()
        print("新的客户端%s已连接!" % str(ip_port))

        # 接收请求并作出响应
        t1 = Thread(target=request_handler, args=(new_client_socket, ip_port))
        t1.start()


if __name__ == '__main__':
    main()

打印结果:

 2.2 返回固定页面

import socket
from threading import Thread


def request_handler(new_client_socket, ip_port):
    """接收信息,并且做出响应"""

    # 接收客户端浏览器发送的请求协议
    request_data = new_client_socket.recv(1024)  # 接收请求报文
    print(request_data)

    # 判断协议是否为空
    if not request_data:
        print("%s客户端已下线!" % str(ip_port))
        new_client_socket.close()
    else:
        # 响应行
        response_line = "HTTP/1.1 200 OK\r\n"

        # 响应头
        response_header = "Server:Python20WS/2.1\r\n"

        # 响应空行
        response_blank = "\r\n"

        # 响应主体
        # 返回字符串内容
        # response_body = "Hello World"

        # 返回固定页面
        with open("static/index.html","rb") as file:
            response_body = file.read()


        # 拼接响应报文
        response_data = (response_line + response_header + response_blank).encode() + response_body

        # 发送响应报文
        new_client_socket.send((response_data))

        # 关闭连接
        new_client_socket.close()

def main():
    """主函数"""

    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 设置地址重用  SOL_SOCKET表示当前套接字,SO_REUSEADDR表示设置地址重用
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

    # 绑定端口
    tcp_server_socket.bind(("", 8080))

    # 设置监听,让套接字由主动变为被动接收
    tcp_server_socket.listen(128)

    while True:
        # 接收客户端连接  定义函数
        new_client_socket, ip_port = tcp_server_socket.accept()
        print("新的客户端%s已连接!" % str(ip_port))

        # 接收请求并作出响应
        t1 = Thread(target=request_handler, args=(new_client_socket, ip_port))
        t1.start()


if __name__ == '__main__':
    main()

前端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试</title>
</head>
<body>
    <h1>网页测试</h1>
</body>
</html>

 结果:

2.3 返回指定的页面

事先准备好前端模板,python服务端代码与static文件夹在同级目录下

 test1.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>Test1</h1>
</body>
</html>

test2.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>Test2</h1>
</body>
</html>

 python服务端:

import socket
from threading import Thread


def request_handler(new_client_socket, ip_port):
    """接收信息,并且做出响应"""

    # 接收客户端浏览器发送的请求协议
    request_data = new_client_socket.recv(1024)  # 接收请求报文
    # print(request_data)

    # 判断协议是否为空
    if not request_data:
        print("%s客户端已下线!" % str(ip_port))
        new_client_socket.close()
    else:
        # 根据客户端浏览器请求的资源路径,返回请求资源
        # 1.把请求协议解码,得到请求报文的字符串
        request_text = request_data.decode()

        # 2.得到请求行
        # 2.1 查找 第一个\r\n出现的位置
        loc = request_text.find("\r\n")

        # 2.2 截取字符串,从开头截取到 第一个\r\n出现的位置
        request_line = request_text[:loc]
        # print(request_line)

        # 2.3 把请求行按照空格拆分,得到列表
        request_line_list = request_line.split(" ")

        # 2.4 得到请求资源路径
        file_path = request_line_list[1]
        print("%s 正在请求:%s" % (str(ip_port), file_path))

        # 响应行
        response_line = "HTTP/1.1 200 OK\r\n"

        # 响应头
        response_header = "Server:Python20WS/2.1\r\n"

        # 响应空行
        response_blank = "\r\n"

        # 响应主体
        # 返回字符串内容
        # response_body = "Hello World"

        # 返回固定页面
        try:
            with open("static"+file_path,"rb") as file:
                response_body = file.read()
        except Exception as e:
            # 重新修改响应行为 404
            response_line = "HTTP/1.1 404 Not Found\r\n"
            response_body = "Error! %s " % str(e)
            response_body = response_body.encode()

        # 拼接响应报文
        response_data = (response_line + response_header + response_blank).encode() + response_body

        # 发送响应报文
        new_client_socket.send((response_data))

        # 关闭连接
        new_client_socket.close()

def main():
    """主函数"""

    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 设置地址重用  SOL_SOCKET表示当前套接字,SO_REUSEADDR表示设置地址重用
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

    # 绑定端口
    tcp_server_socket.bind(("", 8080))

    # 设置监听,让套接字由主动变为被动接收
    tcp_server_socket.listen(128)

    while True:
        # 接收客户端连接  定义函数
        new_client_socket, ip_port = tcp_server_socket.accept()
        print("新的客户端%s已连接!" % str(ip_port))

        # 接收请求并作出响应
        t1 = Thread(target=request_handler, args=(new_client_socket, ip_port))
        t1.start()


if __name__ == '__main__':
    main()

结果:

 

 

下一篇:

python socket 制作http服务器 (面向对象封装) 

本文含有隐藏内容,请 开通VIP 后查看