文章目录
1. socket 模块
socket 又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
可以通过socket() 函数来创建套接字对象:
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
:创建socket对象,走TCP通道socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
:创建socket对象,走UDP通道
socket对象的方法:
tcp相关的方法
方法 | 描述 |
---|---|
listen() | 开始TCP监听,设置操作系统可以挂起的最大连接数量 |
accept() | 被动接受TCP客户端连接,(阻塞式)等待连接的到来 |
connect() | 主动初始化TCP服务器连接 |
send() | 发送TCP数据,发送的数据为bytes类型 |
recv() | 接收TCP数据,返回的数据为bytes类型 |
udp相关的方法
方法 | 描述 |
---|---|
sendto() | 发送UDP数据,发送的数据为bytes类型,并指定发送的地址(ip, port) |
recvfrom() | 接收UDP数据,返回值是(data,address) ,address 就是(ip, port) |
公共方法
方法 | 描述 |
---|---|
bind() | 绑定地址(ip,port) 到套接字, 在AF_INET下,以元组(ip,port) 的形式表示地址 |
close() | 关闭套接字 |
getpeername() | 返回连接套接字的远程地址,返回值通常是元组(ip,port) |
getsockname() | 返回套接字自己的地址,返回值通常是元组(ip,port) |
settimeout(timeout) | 设置套接字操作的超时期,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作,如connect() |
gettimeout() | 返回当前超时期的值 |
2. 通过TCP收发报文
新建文件tcp_server.py
,用于模拟server端。
import sockettcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建socket对象,走tcp通道host = socket.gethostname() # 获取本地主机名port = 1000 # 端口号addr = (host, port)tcpServer.bind(addr) # 绑定地址tcpServer.listen(5) # 设置最大连接数,超过后排队while True: conn,addr = tcpServer.accept() # 建立客户端连接 print(conn) data = conn.recv(1024) # 接收来自客户端的数据,小于1024字节 print(data) msg = 'Hello Client'.encode('utf-8') conn.send(msg) # 发送数据给客户端 conn.close() # 关闭连接
- 本地主机名也可以换成IP地址,如
host = '192.168.1.100'
- server 端需要一直运行,等待 client 端的连接,所以使用
while True
无限循环- 发送的数据必须是bytes类型,所以字符串需要编码
'Hello Client'.encode('utf-8')
,编码后为bytes类型
新建文件tcp_client.py
,用于模拟client端。
import socket tcpClient = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建socket对象host = socket.gethostname() port = 1000 addr = (host, port)tcpClient.connect(addr) # 连接服务,指定主机和端口号data = b'\x01\x64\xff' # 报文数据,bytes类型tcpClient.send(data) # 发送数据给服务端msg = tcpClient.recv(1024) # 接收来自服务端的数据,小于1024字节print(msg.decode('utf-8'))tcpClient.close()
client 端的地址需与 server 端一致,否则会报错:
- IP地址不一致,则会发送数据给其他服务器,可能会出现报错
TimeoutError
- 端口号不一致,会出现报错
ConnectionRefusedError
打开两个cmd
窗口,一个为server端窗口,另一个为client端窗口。
运行顺序,先启动server,后启动client:
- server端窗口,先执行命令
python tcp_server.py
- client端窗口,后执行命令
python tcp_client.py
运行结果如下:
server端窗口:
client端窗口:
注:可以看到server端打印的报文为
b'\x01d\xff'
,看上去与client端发送报文b'\x01\x64\xff'
不一致,实际上是一致的。
\x01d
中的d
为ASCII码,d
对应的16进制的ASCII码正好是64
,也就是说\x01d
其实就是\x01\x64
的缩写而已。
运行如下代码,可以看到两者报文的长度和内容都是一致的:
clientData = b'\x01\x64\xff'serverData = b'\x01d\xff'print(list(clientData)) # [1, 100, 255]print(list(serverData)) # [1, 100, 255]
3. 通过UDP收发报文
新建文件udp_server.py
,用于模拟server端。
import socketudpServer = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 创建socket对象,走udp通道host = socket.gethostname() # 获取本地主机名port = 1000serverAddr = (host, port)udpServer.bind(serverAddr) # 绑定服务端地址while True: clientData,clientAddr = udpServer.recvfrom(1024) # 接收来自客户端的数据 print(clientData,clientAddr) msg = 'Hello Client'.encode('utf-8') udpServer.sendto(msg, clientAddr) # 发送数据给客户端
新建文件udp_client.py
,用于模拟client端。
import socketudpClient = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 创建socket对象,走udp通道host = socket.gethostname() # 获取本地主机名port = 1000serverAddr = (host, port)data = b'\x01\x64\xff' # 报文数据,bytes类型udpClient.sendto(data, serverAddr) # 发送数据给服务端serverData,serverAddr = udpClient.recvfrom(1024) # 接收来自服务端的数据print(serverData.decode('utf-8'), serverAddr)udpClient.close()
打开两个cmd
窗口,一个为server端窗口,另一个为client端窗口。
运行顺序,先启动server,后启动client:
- server端窗口,先执行命令
python udp_server.py
- client端窗口,后执行命令
python udp_client.py
运行结果如下:
server端窗口:
client端窗口:
来源地址:https://blog.csdn.net/aidijava/article/details/127587892