ifconfig 和 ping 命令
ifconfig
ifconfig 是一个用于配置和显示Linux内核中网络接口参数的命令。它可以用来查看和设置网络接口的状态,包括 IP 地址、子网掩码、广播地址等信息。
ping
ping 是一个用于测试网络连接的工具。它发送 ICMP(Internet Control Message Protocol)回显请求到目标主机,并等待回显应答。通过 ping 命令,我们可以测试网络连通性,以及测量网络延迟。
端口和端口号 (共有 65536 个)
端口和端口号是网络通信中的重要概念。
端口
- 端口是数据传输的必经之路,可以视为网络程序之间通信的接口。
- 每运行一个程序都会有一个端口,用于给对应的网络程序发送数据。
端口号
- 端口号用于标识不同的端口,共有 65536 个端口号。
知名端口号 (0-1023)
- 知名端口号是指众所周知的端口号,范围从 0 到 1023。
- 这些端口号一般固定分配给一些服务,比如 21 端口分配给 FTP(文件传输协议)服务,25 端口分配给 SMTP(简单邮件传输协议)服务,80 端口分配给 HTTP 服务。
动态端口号 (1024-65535)
- 动态端口号的范围是从 1024 到 65535。
- 如果程序员开发的程序没有设置端口号,操作系统会在动态端口号这个范围内随机生成一个给开发的应用程序使用。
- 当运行一个程序默认会有一个端口号,当这个程序退出时,所占用的这个端口号就会被释放。
Socket 套接字
Socket(套接字)是网络编程中一个非常基础和重要的概念。它是一种通信机制,允许不同设备上的程序进行数据交换。在网络编程中,套接字用于实现不同主机上的进程之间的通信。
套接字可以分为以下几类:
流式套接字(Stream Sockets):提供面向连接、可靠的数据传输服务,如TCP(传输控制协议)套接字。数据通过TCP套接字传输时,保证数据的顺序和完整性。
数据报套接字(Datagram Sockets):提供无连接的服务,如UDP(用户数据报协议)套接字。数据通过UDP套接字传输时,不保证数据的顺序或完整性,但通常速度更快。
原始套接字(Raw Sockets):允许对较低层次的协议进行访问和控制,通常用于网络诊断和分析。
序列套接字(Sequenced Sockets):提供有序、可靠的、双向的连接,只能用于同一台主机上的进程间通信。
在编程中,套接字的使用通常涉及以下几个步骤:
创建套接字(Socket Creation):使用系统调用创建一个新的套接字。
绑定(Binding):将套接字绑定到一个特定的网络地址和端口上。
监听(Listening):对于服务器端的套接字,需要监听来自客户端的连接请求。
接受连接(Accepting Connections):服务器端套接字接受客户端的连接请求,创建一个新的套接字用于与客户端通信。
连接(Connecting):客户端套接字尝试连接到服务器端的套接字。
数据传输(Data Transfer):一旦连接建立,客户端和服务器端就可以通过套接字进行数据的发送和接收。
关闭连接(Closing Connections):数据传输完成后,需要关闭套接字以释放资源。
在不同的编程语言中,如C、C++、Java、Python等,都有相应的库和API来支持套接字编程。例如,在Python中,可以使用socket模块来创建和管理套接字。
TCP
- TCP(Transmission Control Protocol)简称传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP 的特点
- 面向连接:通信双方必须先建立好连接才能进行数据的传输,并且双方都会为此连接分配必要资源用来记录连接的状态和信息。当数据传输完成后,双方必须断开此连接,以释放系统资源。
- 可靠传输:
- 发送应答机制:通过 TCP 这种方式发送的每个报文段都必须得到接收方的应答才认为这个 TCP 报文段传送成功。
- 超时重传:发送端发送一个报文之后就会启动定时器,如果指定时间内没有得到应答就会重新发送这个报文段。
- 错误校验:TCP 用一个校验和函数来校验数据是否有错误,在发送和接收时都要计算校验和。
- 流量控制和阻塞管理:流量控制用来避免发送端发送过快而使得接收方来不及接收。
通过 TCP 协议,网络程序之间可以实现稳定、可靠的数据传输。
开发 TCP 客户端程序
1.知识要点
- 导入 socket 模块
- 创建 TCP 套接字
socket
参数 1:AF INET,表示 IPv4 地址类型
参数 2:SOCK STREAM,表示 TCP 传输协议类型 - 发送数据
send
参数 1:要发送的二进制数据,注意:字符串需要使用 encode()方法进行编码 - 接收数据
recv
参数 1: 表示每次接收数据的大小,单位是字节 - 关闭套接字
socket表示通信完成
import socket
if __name__ == "__main__":
# 1.创建客户端套接字对象
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.和客户端套接字建立连接
tcp_client_socket.connect(("127.0.0.1", 8080))
# 3.发送数据
tcp_client_socket.send("hello".encode(encoding="utf-8"))
# 4.接受数据 recv阻塞程序
recv_data = tcp_client_socket.recv(1024)
print(recv_data.decode(encoding="utf-8"))
# 5.关闭连接
tcp_client_socket.close()
开发 TCP 服务端程序
TCP 服务端程序开发流程介绍
- 创建服务端端套接字对象
- 绑定 IP 地址和端口号
- 设置监听
- 等待接受客户端的连接请求
- 接收数据
- 发送数据
- 关闭套接字
TCP 服务端程序开发相关函数
| 方法名 | 说明 |
|---|---|
| bind | 绑定 IP 地址和端口号 |
| listen | 设置监听 |
| accept | 等待接受客户端的连接请求 |
| send | 发送数据 |
| recv | 接收数据 |
知识要点
- 导入 socket 模块
- 创建服务端 socket 对象使用 socket 类,
socket.socket(AddressFamily, Type)
- 创建 TCP 套接字
socket
AddressFamily: IP 地址类型,分为 TPv4 和 IPv6AF INET,表示 IPv4 地址类型Type: 传输协议类型SOCK STREAM,表示 TCP 传输协议类型
- 绑定端口号
bind
- 参数 1: 元组,比如:(“”,端口号),元组里面的一个元素是 ip 地址,一般不需要设置,第二个元素是启动程序后使用的端口号。
- 设置监听
listen
- 参数 1: 最大等待连接数
- 等待接受客户端的连接请求
accept - 发送数据
send
- 参数 1: 要发送的二进制数据,注意: 字符串需要使用 encode()方法进行编码
- 接收数据
recv
- 参数 1:表示每次接收数据的大小,单位是字节,注意:解码成字符串使用 decode()方法
- 关闭套接字
socket表示通信完成
注意点
- 当 TCP 客户端程序想要和 TCP 服务端程序进行通信的时候必须要先
建立连接 - TCP 客户端程序一般不需要绑定端口号,因为客户端是主动发起建立连接的。
TCP服务端程序必须绑定端口号,否则客户端找不到这个 TCP 服务端程序。- listen 后的套接字是被动套接字,
只负责接收新的客户端的连接请求,不能收发消息 - 当 TCP 客户端程序和 TCP 服务端程序连接成功后,TCP 服务器端程序会产生一个
新的套接字,收发客户端消息使用该套接字。 - 关闭 accept 返回的套接字意味着和
这个客户端已经通信完毕 当客户端的套接字调用close后,服务器端的recv会解阻塞,返回的数据长度为0,服务端可以通过返回数据的长度来判断客户端是否已经下线,反之服务端关闭套接字,客户端的recv也会解阻塞,返回的数据长度也为0
import socket
if __name__ == "__main__":
# 1. 创建服务端端套接字对象 #参数1: IPv4 参数2: 流式协议
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口复用
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 2. 绑定IP地址和端口号
# tcp_server_socket.bind(("192.168.128.73", 8888))
tcp_server_socket.bind(
("", 8080)
) # 如果bind中的参数第一个ip地址元素设置为"",默认为本机ip地址
# 3. 设置监听
tcp_server_socket.listen(128) # 服务端等待排队连接的最大数量
# 4. 等待接受客户端的连接请求 accept阻塞等待 返回一个用以和客户端的socke,客户端的地址
conn_socket, ip_port = tcp_server_socket.accept()
print("客户端地址:", ip_port)
# 5. 接收数据
recv_data = conn_socket.recv(1024)
print("接收到的数据", recv_data.decode("utf-8"))
# 6. 发送数据
conn_socket.send("客户端发送的数据我收到了".encode("utf-8"))
# 7. 关闭套接字
conn_socket.close()
tcp_server_socket.close()
socket 之 send 和 recv 原理剖析
- TCP socket 的发送和接收缓冲区
当创建一个 TCP socket 对象的时候会有一个发送缓冲区和一个接收缓冲区,这个发送和接收缓冲区指的就是内存中的一片空间。 - send 原理剖析
问:send 是不是直接把数据发给服务端?答:不是,要想发数据,必须得通过网卡发送数据,应用程序是无法直接通过网卡发送数据的,它需要调用操作系统接口也就是说,应用程序把发送的数据先写入到发送缓冲区(内存中的一片空间),再由操作系统控制网卡把发送缓冲区的数据发送给服务端网卡 - recv 原理剖析
问:recv 是不是直接从客户端接收数据?答:不是,应用软件是无法直接通过网卡接收数据的,它需要调用操作系统接口,由操作系统通过网卡接收数据,把接收的数据写入到接收缓冲区(内存中的一片空间),应用程序再从接收缓存区获取客户端发送的数据。
案例-多任务版 TCP 服务端程序开发
- 目前我们开发的 TCP 服务端程序只能服务于一个客户端
- 编写一个 TCP 服务端程序,循环等待接受客户端的连接请求
- 加入多线程来处理多个客户端请求
网址
1. 网址的概念
网址又称为 URL,URL 的英文全拼是(Uniform Resoure Locator),表达的意思是统一资源定位符,通俗理解就是网络资源地址。
2. url 的组成
http 协议
通过HTTP协议来规定浏览器和 web 服务器之间通讯的数据的格式
1. HTTP 协议的概念及作用
HTTP 协议的全称是(HyperText Transfer Protocol),翻译过来就是超文本传输协议。超文本是指在文本数据的基础上还包括非文本数据,非文本数据有图片、音乐、视频等,而这些非文本数据会使用链接的方式进行加载显示,通俗来说超文本就是带有链接的文本数据也就是我们常说的网页数据。
2. HTTP 协议的概念及作用
HTTP 协议的制作者是蒂姆·伯纳斯-李,1991 年设计出来的,
HTTP协议设计之前目的是传输网页数据的,现在允许传输任意类型的数据。传输 HTTP 协议格式的数据是基于 TCP 传输协议的,发送数据之前需要先建立连接。TCP 传输协议是用来保证网络中传输的数据的安全性的,HTTP 协议是用来规定这些数据的具体格式的
注意:
- HTTP 协议规定的数据格式是浏览器和 Web 服务器通信数据的格式,也就是说浏览器和 Web 服务器通信需要使用 HTTP 协议。
3.HTTP 最常见的请求报文有两种:
- GET: 获取 Web 服务器数据
- POST: 向 Web 服务器提交数据
- 一个 HTTP 请求报文可以由请求行、请求头、空行和请求体 4 个部分组成。请求行是由三部分组成: 请求方式 请求资源路径 HTTP 协议版本
- POST 方式的请求报文可以有请求行、请求头、空行、请求体四部分组成。
注意:POST 方式可以允许没有请求体,但是这种格式很少见。
当涉及 HTTP 请求时,以下是一些重要的要点,以及它们在 Markdown 笔记中的整理方式:
HTTP 请求
GET 方法
- 用于获取数据
- 请求行:
GET /user/info HTTP/1.1 - 资源路径:
www.douban.com/movie/top250?start=75&filter=unwatched - 请求头:
- Host: www.example.com
- User-Agent: [指定请求的用户代理]
- Accept: text/html, application/json, text/html,application/json, /
- 请求体: 通常为空
POST 方法
- 用于创建数据
- 请求行:
POST /user/info HTTP/1.1 - 请求头: 同 GET 方法
- 请求体: 包含客户端传输给服务器的其他数据
HTTP 响应
状态行
- 包含协议版本、状态码和状态消息
- 例子:
HTTP/1.1 200 OK
响应状态码
- 2xx: 成功
- 200 OK: 请求成功处理
- 3xx: 需要重定向
- 301 Moved Permanently: 资源永久移动到新地址
- 4xx: 客户端错误
- 400 Bad Request: 服务器无法理解客户端请求
- 401 Unauthorized: 未经授权的请求
- 403 Forbidden: 服务器拒绝提供服务
- 404 Not Found: 请求资源不存在
- 5xx: 服务器错误
- 500 Internal Server Error: 服务器发生不可预期的错误
- 503 Server Unavailable: 服务器当前无法处理客户端请求
响应头
- 包含日期、时间、响应数据类型和编码等信息
响应体
- 包含服务器返回给客户端的数据
这些是 HTTP 请求和响应的基本要素,可以帮助您更好地理解和处理 Web 通信过程中的各个部分。
python 搭建 Web 服务器
1.搭建 Python 自带的静态 Web 服务器
- 知识要点
- 静态 Web 服务器是
为发出请求的浏览器提供静态文档的程序,搭建 Python 自带的 Web 服务器(进入资源文件夹)使用python3 -m http.server 端口号这个命令即可,端口号不指定默认是8000 - 然后就可以在浏览器输入
http://localhost:8000/访问本地服务器
- 静态 Web 服务器是
2.静态 Web 服务器-返回固定页面数据
2.1 开发自己的静态 Web 服务器
- 开发步骤
编写一个 TCP 服务端程序
获取浏览器发送的 HTTP 请求报文数据
读取固定页面数据,把页面数据组装成 HTTP 响应报文数据发送给浏览器。
HTTP 响应报文数据发送完成以后,关闭服务于客户端的套接字。
import socket
if __name__ == "__main__":
# 创建socket
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定地址
tcp_server_socket.bind(("", 8080))
# 设置监听
tcp_server_socket.listen(128)
while True:
# 2.获取浏览器发送到Http请求信息
# 建立连接
client_socket, client_addr = tcp_server_socket.accept()
# 获取浏览器请求消息
client_request_data = client_socket.recv(1024).decode()
print(client_request_data)
# 3. 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
with open(
"python/jupyter_notebooks/python高级编程/网络编程/python搭建静态Web服务器/login.html",
"rb",
) as f:
file_data = f.read()
# 应答行
response_line = "HTTP/1.1 200 OK\r\n"
# 应答头
response_header = "Server:pythonWeb\r\n"
# 应答体
response_body = file_data
response_data = (
response_line + response_header + "\r\n"
).encode() + response_body
client_socket.send(response_data)
# 4.HTTP响应报文数据发送完成以后,关闭服务于客户端的套接宇
client_socket.close()
3.静态 Web 服务器-返回指定页面数据
分析步骤:
- 获取用户请求资源的路径
- 根据请求资源的路径,读取指定文件的数据
- 组装指定文件数据的响应报文,发送给浏览器
- 判断请求的文件在服务端不存在,组装 404 状态的响应报文,发送给浏览器
步骤详解
获取用户请求资源的路径:
- 首先,从客户端请求内容中分割出请求路径。
- 通过将请求内容进行分割,可以获取用户请求的资源路径,这是服务器确定客户端请求的资源所在位置的关键步骤。
根据请求资源的路径,读取请求指定文件的数据:
- 使用 Python 的
open函数以二进制形式读取指定文件的数据。 - 通过将请求路径与服务器静态文件目录拼接,可以读取客户端请求的指定文件的内容。
- 使用 Python 的
组装指定文件数据的响应报文,发送给浏览器:
- 组装包含响应状态行、响应头和响应体的完整 HTTP 响应报文。
- 将响应报文编码为 UTF-8 格式,并通过连接套接字将响应数据发送给浏览器。
判断请求的文件在服务端不存在,组装 404 状态的响应报文,发送给浏览器:
- 使用
try-except块捕获文件打开过程中的异常,通常用于处理文件不存在等错误。 - 如果请求的文件在服务器端不存在,服务器将组装一个包含 404 状态的 HTTP 响应报文,并发送给浏览器,以表明请求资源未找到。
- 使用
这些步骤用于处理客户端请求的静态资源文件,并生成相应的 HTTP 响应
import socket
# 1. 获取用户请求资源的路径
# 2. 根据请求资源的路径,读取指定文件的数据
# 3. 组装指定文件数据的响应报文,发送给浏览器
# 4. 判断请求的文件在服务端不存在,组装404状态的响应报文,发送给浏览器
if __name__ == "__main__":
# 创建socket
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定地址
tcp_server_socket.bind(("", 8080))
# 设置监听
tcp_server_socket.listen(128)
while True:
# 2.获取浏览器发送到Http请求信息
# 建立连接
client_socket, client_addr = tcp_server_socket.accept()
# 获取浏览器请求消息
client_request_data = client_socket.recv(1024).decode()
print(client_request_data)
# 获取用户请求的资源路径
request_data = client_request_data.split(" ")
print("request_data", request_data[1])
request_path = request_data[1]
if request_path == "/":
request_path = "login.html"
try:
# 3. 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
with open(
"python/jupyter_notebooks/python高级编程/网络编程/python搭建静态Web服务器/"
+ request_path,
"rb",
) as f:
file_data = f.read()
except Exception as e:
# 应答行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 应答头
response_header = "Server:pythonWeb\r\n"
# 应答体
response_body = "404 Not Found sorry"
response_data = (
response_line + response_header + "\r\n" + response_body
).encode()
client_socket.send(response_data)
else:
# 应答行
response_line = "HTTP/1.1 200 OK\r\n"
# 应答头
response_header = "Server:pythonWeb\r\n"
# 应答体
response_body = file_data
response_data = (
response_line + response_header + "\r\n"
).encode() + response_body
client_socket.send(response_data)
# 4.HTTP响应报文数据发送完成以后,关闭服务于客户端的套接宇
finally:
client_socket.close()
4.多任务版
- 多线程 当客户端和服务端建立连接成功,创建子线程,使用子线程专门处理客户端的请求,防止主线程阻塞
- 多进程
import socket
import threading
# 1. 获取用户请求资源的路径
# 2. 根据请求资源的路径,读取指定文件的数据
# 3. 组装指定文件数据的响应报文,发送给浏览器
# 4. 判断请求的文件在服务端不存在,组装404状态的响应报文,发送给浏览器
def handle_client_request(client_socket):
# 获取浏览器请求消息
client_request_data = client_socket.recv(1024).decode()
print(client_request_data)
# 获取用户请求的资源路径
request_data = client_request_data.split(" ")
print("request_data", request_data[1])
# 判断客户端是否关闭
if len(request_data) == 1:
client_socket.close()
print("客户端关闭")
return
request_path = request_data[1]
if request_path == "/":
request_path = "login.html"
try:
# 3. 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
with open(
"python/jupyter_notebooks/python高级编程/网络编程/python搭建静态Web服务器/"
+ request_path,
"rb",
) as f:
file_data = f.read()
except Exception as e:
# 应答行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 应答头
response_header = "Server:pythonWeb\r\n"
# 应答体
response_body = "404 Not Found sorry"
response_data = (
response_line + response_header + "\r\n" + response_body
).encode()
client_socket.send(response_data)
else:
# 应答行
response_line = "HTTP/1.1 200 OK\r\n"
# 应答头
response_header = "Server:pythonWeb\r\n"
# 应答体
response_body = file_data
response_data = (
response_line + response_header + "\r\n"
).encode() + response_body
client_socket.send(response_data)
# 4.HTTP响应报文数据发送完成以后,关闭服务于客户端的套接宇
finally:
client_socket.close()
if __name__ == "__main__":
# 创建socket
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定地址
tcp_server_socket.bind(("", 8080))
# 设置监听
tcp_server_socket.listen(128)
while True:
# 2.获取浏览器发送到Http请求信息
# 建立连接
client_socket, client_addr = tcp_server_socket.accept()
# 创建子线程
sub_thread = threading.Thread(
target=handle_client_request, args=(client_socket,)
)
sub_thread.start()
5.静态 Web 服务器-面向对象开发
分析步骤:
把提供服务的 Web 服务器抽象成一个类(HTTPWebServer)提供 Web 服务器的初始化方法,在初始化方法里面创建 Socket 对象
5.1 知识要点
- 把提供服务的 Web 服务器抽象成一个类(HTTPWebServer)
class HttpWebServer(object): - 提供 Web 服务器的初始化方法,在初始化方法里面创建 socket 对象
def __init__ (self):
初始化服务端套接字,设置监听,代码省略.. - 提供一个开启 Web 服务器的方法,让 Web 服务器处理客户端请求操作
def start(self):
import socket
import sys
import threading
import pdb
class HttpWebServer:
def __init__(self, port) -> None:
# 创建socket
self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定地址
self.tcp_server_socket.bind(("", port))
# 设置监听
self.tcp_server_socket.listen(128)
def handle_client_request(self, client_socket):
# pdb.set_trace()
# 获取浏览器请求消息
client_request_data = client_socket.recv(1024).decode()
print(client_request_data)
# 获取用户请求的资源路径
request_data = client_request_data.split(" ")
print("request_data", request_data[1])
# 判断客户端是否关闭
if len(request_data) == 1:
client_socket.close()
print("客户端关闭")
return
request_path = request_data[1]
if request_path == "/":
request_path = "/login.html"
try:
# 3. 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
with open(
"D:/MyCode/VSCode/python/jupyter_notebooks/python高级编程/网络编程/python搭建静态Web服务器"
+ request_path,
"rb",
) as f:
file_data = f.read()
except Exception as e:
print(e)
# 应答行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 应答头
response_header = "Server:pythonWeb\r\n"
# 应答体
response_body = "404 Not Found sorry"
response_data = (
response_line + response_header + "\r\n" + response_body
).encode()
client_socket.send(response_data)
else:
# 应答行
response_line = "HTTP/1.1 200 OK\r\n"
# 应答头
response_header = "Server:pythonWeb\r\n"
# 应答体
response_body = file_data
response_data = (
response_line + response_header + "\r\n"
).encode() + response_body
client_socket.send(response_data)
# 4.HTTP响应报文数据发送完成以后,关闭服务于客户端的套接宇
finally:
client_socket.close()
def start(self):
while True:
# 2.获取浏览器发送到Http请求信息
# 建立连接
client_socket, client_addr = self.tcp_server_socket.accept()
# 创建子线程
sub_thread = threading.Thread(
target=self.handle_client_request, args=(client_socket,)
)
sub_thread.start()
def main():
print(sys.argv)
if not len(sys.argv) == 2:
print("格式错误1 python xxx.py port_id")
return
if not sys.argv[1].isdigit():
print("格式错误2 python xxx.py port_id")
return
port = int(sys.argv[1])
# 创建一个服务器对象
my_web_server = HttpWebServer(port)
# 开启服务器
my_web_server.start()
if __name__ == "__main__":
main()
6.命令行动态设定端口号
import sys
print(sys.argv) # 命令行的参数列表 例如 python test.py 8080







