python修炼——http 初识!

昨日回顾

正则

贪婪:会尽可能多的去匹配

非贪婪:会尽可能少的去匹配

?变为非贪婪

\d?? 匹配数字 0 次 等价于 [^\d] 匹配非数字

在字符串前面加上 r 表示原生字符串

匹配单个字符:. , \d, \D, \s, \S, \w, \W

匹配多个字符:*,+,?,{}

匹配开头结尾:^, $

匹配分组:|, (), \num, (?p\), (?p=name)

re 高级:re.match(), re.search(), re.findall(), re.sub(), re.split(),

今日内容

http 协议

超文本传输协议(HTTP: HyperText Transfer Protocol)

电脑之间传输数据的协议

传输的是 bytes(字节) 类型的数据

http 分类

http 请求:http request http 响应: http response

request 请求

​ 请求头:request headers

​ GET

​ Accept-Encoding: 压缩

​ Accept-Language: 语言

​ User-Agent: 标识你的电脑手机

​ \r\n 空行

​ 请求体: request body

​ 是穷让你如此正直

response 响应

​ HTTP\1.1 200 OK 注意:HTTP必须大写, 换行是 \r\n 不单单只是 \n

​ 响应头和响应体之间必须有个空行 \r\n

​ response status line 响应状态行

​ index.html 访问的默认的主页

​ 响应头

​ 响应体

  • Elements显示网页的结构
  • Network显示浏览器和服务器的通信
tcp 三次握手,四次挥手

三次握手:

在用 tcp 传输数据时,需要先建立连接,用三次握手建立传输数据的连接通道

其实是服务端端和客户端各自都在准备资源。

  • 第一次握手:客户端向服务器发送连接请求包,标志位 SYN (同步序号)置为 seq = X;
  • 第二次握手:服务器收到客户端发过来的报文,由 SYN = X 知道客户端要求建立联机,向客户端发送一个包含 SYN 和 ACK 的 TCP 报文,其中服务器向客户端发送连接请求包,标志位 SYN (同步序列)置为 Y=1;将确认序号(ACK)设置为客户的序列号加 1,即 X + 1
  • 第三次握手:客户端收到服务器发来的包后检查确认序号(ACK)是否正确,即第一次发送的序号加1(X+1);若正确,服务器再次打算确认序号(ACK) = Y+1;服务器收到确认序号值 ACK=2 则连接成功,可以传送数据了。

四次挥手:

  • 第一次挥手:客户端给服务器发送 TCP 包,用来关闭客户端到服务器的数据传送,将标志位 FIN 置为 X 和 ACK 置为 Y ;
  • 第二次挥手:服务器收到 FIN 后,返回一个 ACK(标志位ACK=1)确认序号为收到的序号加1,即 X+1
  • 第三次挥手:服务器关闭与客户端的连接,发送一个 FIN,标志位 FIN和 ACK 置为1,序号为 Y
  • 第四次挥手:客户端收到服务器发送的 FIN 之后,发回 ACK 确认,确认序号为收到的序号加1,即Y+1,服务器手机 ACK 为 Y+1 后关闭

在第二次和第三次、第三次和第四次之间会有超时等待。

"""
一个简单的http服务器
创建http服务器,  tcp
"""
import socket
import re


def service_client(client_socket):
    """实现接收消息和发送消息"""
    # 接收客户发送过来的请求
    request = client_socket.recv(1024).decode("utf-8")
    print(">>>" * 20)
    print(request)

    # 将客户端的请求变成列表
    request_lines = request.splitlines()
    print(request_lines)

    # 使用正则取出客户端请求的数据名称
    # request_lines = ['GET /images/trolltech-logo.png HTTP/1.1', 'Host: 127.0.0.1:8888']
    #  从中取出 /images/trolltech-logo.png
    ret = re.match(r"[^/]+(/[^ ]*) HTTP/1.1", request_lines[0])
    client_request = ""
    if ret:
        print("客户端请求的数据是 %s" % ret.group(1))
        client_request = ret.group(1)
        if client_request == "/":
            client_request = "/index.html"

    try:
        f = open("./html%s" % client_request, "rb")
    except:
        response_status_line = "HTTP/1.1 404 NOT FOUNT\r\n"
        space_line = "\r\n"
        response_header = response_status_line + space_line
        response_body = "<h1>FILE NOT FOUND</h1>".encode("utf-8")
    else:
        html_content = f.read()
        f.close()

        # 根据客户需求回送数据过去
        response_status_line = "HTTP/1.1 200 OK\r\n"  # response status line 响应状态行   HTTP 必须大写   换行是\r\n
        space_line = "\r\n"  # 响应头和响应的数据之间有个空行
        response_body = html_content  # 发送的内容
        response_header = response_status_line + space_line

    client_socket.send(response_header.encode("utf-8"))  # 注意:响应头是str格式,需要编码
    client_socket.send(response_body)  # 响应的内容需要是字节模式,不需要进行编码发送,浏览器会自动解析
    # 关闭这个套接字
    client_socket.close()


def main():
    # 创建服务器的套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 可以让端口重复使用

    # 绑定本地信息
    tcp_server_socket.bind(("", 8888))  # 地址信息放在元组中

    # 将套接字变为监听
    tcp_server_socket.listen()  # 最大的客户端链接数为128

    while True:
        # 等待客户端链接
        # 如果有客户端链接,会返回元组,第一个元素是一个新的套接字专为这个客户端服务,第二个元素是客户端地址信息
        new_socket, client_addr = tcp_server_socket.accept()

        # 循环和客户的进行通信
        service_client(new_socket)

    # 关闭监听套接字
    tcp_server_socket.close()


if __name__ == '__main__':
    main()

HTTP 初学,有很多要记忆的知识,慢慢来,把代码多撸几遍好了!!!

猜你喜欢

转载自blog.csdn.net/qyf__123/article/details/81879716