作者:我是王美慧 | 来源:互联网 | 2023-02-01 13:00
目录昨日回顾软件开发架构CS架构BS架构网络编程互联网协议socket套接字今日内容一、subprocess模块二、粘包问题三、struct模块四、UDP五、QQ聊天室六、Sock
目录
- 昨日回顾
- 今日内容
- 一、subprocess模块
- 二、粘包问题
- 三、struct模块
- 四、UDP
- 五、QQ聊天室
- 六、SocketServer
昨日回顾
软件开发架构
C/S架构
B/S架构
Broser:浏览器
Server:服务端
优点
用户不需要下载多个客户端,以浏览器充当所有软件的客户端
缺点
网络资源占用较大,网络不稳定时,软件的使用也不稳定
网络编程
互联网协议
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
物理层
数据链路层
把二进制数据交给"以太网协议"处理:
规定好电信号的分组方式
必须要有一个网卡
mac的地址
由12位唯一的编码
前6位:厂商号
后6位:流水号
以太网协议
交换机
让多台电脑连接在一起
互联网
让所有电脑都互联到一起
网络层
连接到互联的电脑都需要有一个IP地址
- IP地址
- 用于唯一标识计算机(局域网)具体位置
- 点分十进制
- 最小值:0.0.0.0
- 最最大值:255.255.255.255
传输层
TCP/UDP协议
TCP:流式协议
基于TCP协议进行通信,必须要创建双向通道
- 一个是客户端往服务端的管道
- 一个是服务端往客户端的管道
三次握手,四次挥手
应用层
socket套接字
# 服务端.py
import socket
server = socket.socket()
server.bind(('127.0.0.1',8888))
server.listen(5) # 半连接池
while True:
conn,addr = server.accept()
while True:
try:
data = conn.recv(1024).decode('utf-8') # recv数据从内存中获取
if data == 'q':
break
print(data)
conn.send(data.encode('utf-8'))
except Exception as e:
print(e)
break
conn.close()
# 客户端.py
import socket
client = socket.socket()
client.connect(('127.0.0.1'.8888))
while True:
msg = input('>>')
client.send(msg.encode('utf-8'))
if msg == 'q':
break
data = client.recv(1024).decode('utf-8')
print(data)
client.close()
今日内容
一、subprocess模块
可以通过代码执行操作系统的终端命令
并返回终端执行命令的结果
import subprocess
cmd = input('cmd>>>:')
obj = subprocess.popen(
cmd, # cmd命令
Shell = True,
stdout = subprocess.PIPE, # 返回正确结果
stderr = subprocess.PIPE # 返回错误结果
)
data1 = obj.stdout.read()
data2 = obj.stderr.read()
result = data1 + data2
print(result.decode('gbk'))
二、粘包问题
三、struct模块
解决粘包问题, 是一个可以将很长的数据的长度,压缩成固定的一个标记(数据包头)
import struct
# 打包压缩
# i:模式,会将数据长度压缩成4个bytes
str = '1123fsgsdasfdasfaa'
# 模拟客户端
# 包头
headers = struct.pack('i',len(str))
print(len(headers)) # 4
# 模拟服务端
# headers = conn.recv(4)
datalen = struct.unpack('i',headers) # 元组(len(str),)
print(data_len[0]) # len(str)
既想发送文件,又想发送文件的描述信息
客户端发送字典给服务端
# 服务端.py
import socket
import json
import struct
server = socket.socket()
server.bind(
('127.0.0.1', 9527)
)
server.listen(5)
while True:
conn, addr = server.accept()
while True:
try:
# 先接收报头
headers = conn.recv(4)
# 解包获取真实数据长度
data_len = struct.unpack('i', headers)[0]
# 获取字典数据真实长度
bytes_data = conn.recv(data_len)
back_dic = json.loads(bytes_data.decode('utf-8'))
print(back_dic)
except Exception as e:
print(e)
break
conn.close()
# 客户端.py
import socket
import struct
import json
import time
client = socket.socket()
client.connect(
('127.0.0.1', 9527)
)
while True:
send_dic = {
'file_name': 'jason真实写真集.avi',
'file_size': 10000000 # 10G
}
# json序列化,并转码成bytes类型数据
json_data = json.dumps(send_dic)
bytes_data = json_data.encode('utf-8')
# 先做报头
headers = struct.pack('i', len(bytes_data))
client.send(headers)
client.send(bytes_data)
time.sleep(10)
四、UDP
UDP是一种传输协议
- 不需要建立双向通道
- 不会粘包
- 客户端给服务端发送数据不需要等待服务端返回接受成功
- 数据容易丢失,不安全
# 服务端
import socket
# SOCK_DGRAM:代表UDP
server = socket.scoket(type = socket.SOCK_DGRAM)
server.bind(('127.0.0.1',9527))
msg, addr = server.recvfrom(1024)
# 客户端
import socket
client = socket.socket(type = socket.SOCK_DGRAM)
server_ip_port = ('127.0.0.1',9527)
client.sendto(b'hello',server_ip_port)
五、QQ聊天室
基于UDP实现QQ聊天室
# 服务端
import socket
server = socket.socket(type = socket.SOCK_DGRAM)
server.bind(('127.0.0.1',9527))
while True:
msg,addr = server.recvfrom(1024)
print(addr)
print(msg.decode('utf-8'))
send_msg = input('服务端:')
server.sendto(send_msg.encode('utf-8'),addr)
# 客户端
import socket
client = socket.socket(type = socket.SOCK_DGRAM)
addr= ('127.0.0.1',9527)
while True:
send_msg = input('客户端1:')
client.sendto(send_msg.encode('utf-8'),addr)
back_msg ,addr= client.recvfrom(1024)
print(back_msg.decode('utf-8'))
六、SocketServer
python内置模块,可以简化socket套接字TCP/UDP服务端的代码
import socketserver
# 定义类
class MyTcpServer(socketserver.BaseRequestHandler)
# 重新父类的handler
def handler(self):
# 1. 接收消息
data = self.request.recv() # conn.recv(1024)
# 2. 给客户端发送消息
send_msg = input('服务端:').encode('utf-8')
self.request.send(send_msg)
if __name__= '__main__':
server = socketserver.TCPserver(('127.0.0.1',8888),MyTcpServer)
server.serve_forever()