昨日回顾
正则
贪婪:会尽可能多的去匹配
非贪婪:会尽可能少的去匹配
?变为非贪婪
\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 初学,有很多要记忆的知识,慢慢来,把代码多撸几遍好了!!!