python网络编程(四)
2022/6/8 1:21:24
本文主要是介绍python网络编程(四),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
应用层编程
应用层
-
应用层定义了各种各样的协议来规范数据格式,常见的有HTTP、FTP、SMTP等,HTTP是一种比较常用的应用层协议
-
HTTP
HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网上应用最为广泛的一种网络协议,它是基于TCP的应用层协议客户端和服务端进行通信的规则,它的模式非常简单,就是客户端发起请求,服务端相应请求
-
请求行:包含请求方法、请求地址和HTTP协议版本。
-
消息报头:包含了一系列的键值对。
-
请求正文(可选):注意和消息报头之间有一个空行。
服务端相应响应
-
状态行:包含HTTP协议版本、状态码和状态描述,以空格分隔。
-
相应头:消息报头,包含一系列的键值对。
-
响应正文:返回内容,注意和响应之间有一个空行。
-
-
请求方法
- GET:从服务器获取指定(请求地址)的资源的信息,它通常只用于读取数据,就像数据库查询一样,不会对资源进行修改。
- POST:想指定资源提交数据(比如提交表单,上传文件),请求服务器进行处理。数据被包含在请求正文中,这个请求可能会创建新的资源或更新现有的资源。
- PUT:通过指定资源的唯一表识(在服务器上的具体存放位置),请求服务器创建或更新资源。
- DELETE:请求服务器删除指定资源。
- HEAD:与GET方法类似,从服务器获取资源信息,和GET方法不同的是,HEAD不含有呈现数据,仅仅是HTTP头信息。HEAD的好处在于,只用这个方法可以在不必传输全部的内容情况下,就可以获取资源的元信息(或元数据)。
- OPTIONS:该方法可使服务器传回资源所支持的所有HTTP请求方法。
-
状态码
- 1XX消息:请求已被服务接收,继续处理。
- 2XX成功:请求已成功被服务器接收、理解、并接受
- 200:OK
- 201:Created 已创建
- 202:Accepted 接收
- 203:Non- Authoritative Information 非认证消息
- 204:No Content 无内容
- 3XX重定向:需要后续操作才能完成这一请求
- 301:Moved Permanently 请求永久重定向
- 302:Moved Temporarily 请求临时重定向
- 304:Not Modified 文件为修改,可以直接使用缓存的文件
- 305:Use Proxy 使用代理
- 4XX请求错误:请求含有词法错误或者无法被执行
- 400:Bad Request 由于客户端请求有语法错误,不能被服务器所理解。
- 401:Unauthorized 请求未经授权。这个状态代码必须和WWW- Authenticate报头域一起使用。
- 403:Forbidden 服务器收到请求,但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因。
- 404:Not Found 请求的资源不存在,例如,输入错了URL或者服务端没有启动。
- 5XX服务器错误:服务器在处理某个正确请求是发生错误
- 500:Internal Server Error 服务器发生不可预期的错误,导致无法完成客户端的请求。
- 503:Service Unavailable 服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常。
- 504:Gateway Time-out 网关超时。
Python 实现文本服务器
-
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可以查看请求和响应信息,与后台输出一致
Python 实现Html服务器
-
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
后台数据为:
HTTP数据流传输过程
宏观层面
-
当网页上输入域名之后,会先去本机上的
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需要与目的服务器三次握手,三次握手的流程为:
- 我向目的服务器发送消息(SYN)
- 服务器应答并给我发送消息(SYN、ACK)
- 我应答(ACK)
-
三次握手成功后,开始使用HTTP协议请求网页内容。发送HTTP请求报文,服务器给出应答。
-
如果服务器禁止访问就会回复“Forbidden”或者“file not found”等,如果服务器正常则会回复“OK”,以及200的状态码,并传回相应的数据,若传回的数据是HTML形式的文本,浏览器就会将数据渲染到屏幕上。
微观层面
- 域名解析
- 浏览器向本机DNS模块发出DNS请求,DNS模块生成相关的DNS报文;
- DNS模块将生成的DNS报文传递给传输层的UDP协议单元;
- UDP协议单元将该数据封装成UDP数据报,传递给网络层的IP协议单元;
- IP协议单元将该数据封装成IP数据包,其目的IP地址为DNS服务器的IP地址;
- 封装好的IP数据包将传递给数据链路层的协议单元进行发送;
- 发送时在ARP缓存中查询相关数据,如果没有,就发送ARP广播(包含代查询的IP地址,收到广播的主机检查自己的IP,符合条件的主机将含有自己MAC地址的ARP包发送给ARP广播的主机)请求,等待ARP回应;
- 得到ARP回应后,将IP地址(目的IP地址)与路由的下一跳MAC地址(DNS的MAC地址)对应的信息写入ARP缓存表;
- 写入缓存表后,以路由下一跳的地址(DNS的MAC地址)填充目的地址,以数据帧形式转发;
- 转发可能会经过多次;
- DNS请求到达DNS服务器的数据链路层协议单元;
- DNS服务器的数据链路层协议单元解析数据帧,将内部的IP数据包传递给网络层IP协议单元;
- DNS服务器的IP协议单元解析IP数据包,将内部的UDP数据报传递给传输层协议单元;
- DNS服务器的UDP协议单元解析收到的UDP数据报,将内部的DNS报文传递给DNS服务单元;
- DNS服务单元将域名解析成对应的IP地址,产生DNS回应报文;
- DNS回应报文->UDP->IP->MAC->我的主机;
- 我的主机收到数据帧,将数据帧->IP->UDP->浏览器;
- 将域名解析结果以域名和IP地址对应的形式写入DNS缓存表;
- TCP三次握手
- 向目的主机发送TCP连接8请求报文;
- 该TCP报文中SYN标志位设为1,表示连接请求;
- 该TCP报文通过IP(DNS)->MAC(ARP)->网关->目的主机;
- 目的主机收到数据帧,通过IP->TCP,TCP协议单元回应请求应答报文;
- 该报文中SYN和ACK标志设为1,表示连接请求应答;
- 该TCP报文通过IP(DNS)->MAC(ARP)->网关->我的主机;
- 我的主机收到数据帧,通过IP->TCP,TCP协议单元回应请求确认报文(ACK)
- 该TCP报文通过IP(DNS)->MAC(ARP)->网关->目的主机‘
- 目的主机收到数据帧,通过IP->TCP,连接建立完成;
- HTTP传输数据
- 浏览器向域名发出请求;
- 该请求报文通过HTTP->TCP->IP(DNS)->MAC(ARP)->网关->目的主机;
- 目的主机收到数据帧,通过IP->TCP->HTTP,HTTP协议单元会回应HTTP协议格式封装好的HTML形式数据;
- 该HTML数据通过TCP->IP(DNS)->MAC(ARP)->网关->我的主机;
- 我的主机收到数据帧,通过IP->TCP->HTTP->浏览器,浏览器以网页的形式显示HTML内容;
- TCP四次挥手
- 浏览器向目的主机发出TCP连接结束请求报文,此时进入FIN WAIT状态;
- 该报文FIN标志位设为1,表示结束请求;
- TCP结束请求报文通过IP(DNS)->MAC(ARP)->网关->目的主机;
- 目的主机收到数据帧,通过IP->TCP,TCP协议单元回应结束应答报文(ACK);
- 当前只是进行回应,因为目的主机可能还有数据要传,并不着急断开连接;
- 该报文中ACK标志位设为1,表示收到结束请求;
- 目的数据发送完所有数据后,向我的主机发出TCP连接结束请求报文;
- 该报文FIN标志位设为1,表示结束请求;
- TCP结束请求报文通过IP(DNS)->MAC(ARP)->网关->我的主机;
- 我的主机收到数据帧,通过IP->TCP,TCP协议单元回应应答报文,此时进入TIME WAIT状态,因为不相信网络时可靠的,如果目的主机没收到还可以重发;
- 该报文中的FIN标志位均设为1,表示结束应答;
- 该TCP回应报文通过IP(DNS)->MAC(ARP)->网关->目的主机;
- 目的主机关闭连接;
- TIME WAIT等待结束后,没有收到回复,说明目的正常关闭了,我的主机也关闭连接;
应用层协议
DHCP动态主机分配协议
-
DHCP,主机动态配置协议,是一个局域网的网络协议,使用UDP协议工作,常用的2个端口:67(DHCP service),68(DHCP client)。
DHCP通常被用于局域网环境,主要作用是集中的管理、分配IP地址,使client动态的获得IP地址、Gateway地址、DNS服务器地址等信息,并能够提升地址的使用率。
-
DHCP工作流程
这篇关于python网络编程(四)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-21Python编程基础教程
- 2024-11-20Python编程基础与实践
- 2024-11-20Python编程基础与高级应用
- 2024-11-19Python 基础编程教程
- 2024-11-19Python基础入门教程
- 2024-11-17在FastAPI项目中添加一个生产级别的数据库——本地环境搭建指南
- 2024-11-16`PyMuPDF4LLM`:提取PDF数据的神器
- 2024-11-16四种数据科学Web界面框架快速对比:Rio、Reflex、Streamlit和Plotly Dash
- 2024-11-14获取参数学习:Python编程入门教程
- 2024-11-14Python编程基础入门