应用层定义了各种各样的协议来规范数据格式,常见的有HTTP、FTP、SMTP等,HTTP是一种比较常用的应用层协议
HTTP
HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网上应用最为广泛的一种网络协议,它是基于TCP的应用层协议客户端和服务端进行通信的规则,它的模式非常简单,就是客户端发起请求,服务端相应请求
请求行:包含请求方法、请求地址和HTTP协议版本。
消息报头:包含了一系列的键值对。
请求正文(可选):注意和消息报头之间有一个空行。
服务端相应响应
状态行:包含HTTP协议版本、状态码和状态描述,以空格分隔。
相应头:消息报头,包含一系列的键值对。
响应正文:返回内容,注意和响应之间有一个空行。
请求方法
状态码
server.py
import socket import threading def handle_client(client: socket.socket, address): # 接收客户端的请求 request_data = client.recv(1024) # 打印数据 print(f"客户端的地址为:{address},请求的数据为:{request_data.decode()}") # 向客户端相应数据,相应的格式是要遵循HTTP协议规范 # 状态行:包含HTTP协议的版本、状态码和状态描述符,以空格相隔 response_status = "HTTP/1.1 200 OK\r\n" # 自定义响应头 response_header = "Server:New Server\r\n" # 相应体 response_body = "Hello World" # 组装响应数据 response = response_status + response_header + '\r\n' + response_body # 将数据回复给客户端 client.send(response.encode()) # 关闭client client.close() def main(): # 创建一个TCP的HTTP服务器 with socket.socket(type=socket.SOCK_STREAM) as server: # 如果地址什么都不写,代表着绑定着是我当前机器的所有IP地址 server.bind(("", 8080)) # 服务器监听 server.listen(128) # 打印启动信息 print("服务器已经启动!") # 不停的接收客户端的请求 while True: # 接收客户端的请求,返回客户端的socket和address client, address = server.accept() # 采用多线程处理多个客户端的请求 thread = threading.Thread(target=handle_client, args=(client, address)) # 启动线程 thread.start() if __name__ == '__main__': main()
运行后在网页输入127.0.0.1:8080
后台打印出请求行和消息报头
通过F12可以查看请求和响应信息,与后台输出一致
server.py
import socket import threading import os # 存放html的路径,我放在D盘下的 HTML_PATH = "D:\\" def handle_client(client: socket.socket, address): # 接收客户端的请求 request_data = client.recv(1024) # 打印数据 print(f"客户端的地址为:{address},请求的数据为:{request_data.decode()}") # 通过空格分隔客户端请求数据 # 请求行:GET / HTTP/1.1 ==> 请求方法、请求地址和HTTP协议版本 request = request_data.decode().split(" ") # 拿到客户端请求的文件,也就是请求地址。例如:index.html if request[1] == '/': filename = '/index.html' else: filename = request[1]] # 向客户端相应数据,相应的格式是要遵循HTTP协议规范 # 状态行:包含HTTP协议的版本、状态码和状态描述符,以空格相隔 response_status = "HTTP/1.1 200 OK\r\n" # 自定义响应头 response_header = "Server:New Server\r\n" # 有可能客户端请求的是图片或者视频文件,所以需要用rb的形式读取 try: with open(os.path.join(HTML_PATH, filename), 'rb') as f: # 响应体 response_body = f.read().decode() except Exception as e: _ = e response_status = "HTTP/1.1 404 Not Found\r\n" response_body = "File Not Found" # 组装响应数据 response = response_status + response_header + '\r\n' + response_body # 将数据回复给客户端 client.send(response.encode()) # 关闭client client.close() def main(): # 创建一个TCP的HTTP服务器 with socket.socket(type=socket.SOCK_STREAM) as server: # 如果地址什么都不写,代表着绑定着是我当前机器的所有IP地址 server.bind(("", 8080))) # 服务器监听 server.listen(128) # 打印启动信息 print("服务器已经启动!") # 不停的接收客户端的请求 while True: # 接收客户端的请求,返回客户端的socket和address client, address = server.accept() # 采用多线程处理多个客户端的请求 thread = threading.Thread(target=handle_client, args=(client, address)) # 启动线程 thread.start() if __name__ == '__main__': main()
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My Web Server</title> </head> <body> <h1>Hello World</h1> </body> </html>
运行server.py
,浏览器输入http://127.0.0.1:8080
后台的数据为:
浏览器输入http://127.0.0.1:8080/index.html
后台的数据为:
浏览器输入http://127.0.0.1:8080/index1.html
后台数据为:
当网页上输入域名之后,会先去本机上的Host
文件当中获取对应的IP地址,如果能取到,则使用Host
文件的解析结果。
格式:IP地址 + 空格 + 域名
Windows: C:\Windows\system32\drivers\etc\hosts
Mac: /private/etc/hosts
Linux: /etc/hosts
如果Host
文件中没有该域名的解析结果,那么就会去使用DNS协议来获取IP。在DNS协议中,PC会向你的本地DNS服务器获取对应的IP地址信息。本地DNS服务器的IP路由分为两种:通过手动设置的静态IP地址,通过动态DHCP协议获取动态IP地址。
接下来建立TCP连接。在TCP协议中,建立TCP需要与目的服务器三次握手,三次握手的流程为:
三次握手成功后,开始使用HTTP协议请求网页内容。发送HTTP请求报文,服务器给出应答。
如果服务器禁止访问就会回复“Forbidden”或者“file not found”等,如果服务器正常则会回复“OK”,以及200的状态码,并传回相应的数据,若传回的数据是HTML形式的文本,浏览器就会将数据渲染到屏幕上。
DHCP,主机动态配置协议,是一个局域网的网络协议,使用UDP协议工作,常用的2个端口:67(DHCP service),68(DHCP client)。
DHCP通常被用于局域网环境,主要作用是集中的管理、分配IP地址,使client动态的获得IP地址、Gateway地址、DNS服务器地址等信息,并能够提升地址的使用率。
DHCP工作流程