一、业务逻辑
客服端与服务端创立连接后,客服端发送目录下图片名,图片通过Python中的 struct 标准库的pack()方法,将数据转换为 '128sq'格式的字节串,字节串包括编码方式为 utf-8 和图片大小,发送给服务端。通过open()方法打开目录下图片,并以二进制1027字节读取图片,发送给客服端。
服务端通过计算给定 ’128sq‘格式字符串大小在接受客户端数据,通过 struct 模块中的 unpack()方法以 ‘128sq’将数据解包,并存入以二进制写入权限的文件中
服务端源码:
import socket
import os
import sys
import struct
def socket_service_image():
try:
# 创建套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 用于设置套接字的选项值
# socket.setsockopt(level, option, value)
# level:设置选项级别,表示选项适用的协议层
# option:要设置的选项
# value:选项的值
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 设置ip地址和端口号
s.bind(('192.168.8.101', 8899))
# 监听数
s.listen(10)
# 异步处理
except socket.error as msg:
print(msg)
sys.exit(1)
print('Wait for Connection…………')
while True:
# 用于接受一个传入的连接请求,并返回一个新的套接字对象和客户端地址
sock, addr = s.accept() # addr 是一个元组(ip, port)
deal_image(sock, addr)
def deal_image(sock, addr):
print('Accept connection from {0}'.format(addr)) # 查看发送端的ip和端口
while True:
# Python的 struct 模块中的一个函数,用于计算给定格式字符串的字节大小
# struct.calcsize(format)
# format 要计算字节大小的格式字符串
fileinfo_size = struct.calcsize('128sq')
# 用于从套接字接收数据
# socket.recv(buffer_size)
# buffer_size 要接收的数据的最大字节数
buf = sock.recv(fileinfo_size) # 接受图片名
if buf:
# Python的 struct 模块中的一个函数,用于将字符串解包为对应的数据类型
filename, filesize = struct.unpack('128sq', buf)
fn = filename.decode().strip('\x00')
new_filename = os.path.join(
'./client_image/',
'new_' + fn
) # 在服务器端新建图片名
recvd_size = 0
fp = open(new_filename, 'wb')
while not recvd_size == filesize:
if filesize - recvd_size > 1024:
# 用于从套接字接收数据
# socket.recv(buffer_size)
# buffer_size 要接收的数据的最大字节数
data = sock.recv(1024)
recvd_size += len(data)
else:
# 用于从套接字接收数据
# socket.recv(buffer_size)
# buffer_size 要接收的数据的最大字节数
data = sock.recv(1024)
recvd_size = filesize
fp.write(data) # 写入图片数据
fp.close()
sock.close()
break
if __name__ == '__main__':
socket_service_image()
客户端源码:
import socket
import os
import sys
import struct
def sock_client_image():
while True:
try:
# 创建套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置ip地址和端口号
s.connect(('192.168.8.101', 8899))
# 异步处理
except socket.error as msg:
print(msg)
print(sys.exit())
filepath = input('input the file:') # 输入当前目录下的图片名 xxx.jpg
# Python中的一个函数,用于将数据转换为指定格式的字节串
fhead = struct.pack(
b'128sq',
bytes(
# Python中 os.path 模块的一个函数,用于文件路径中获取文件部分
os.path.basename(filepath),
encoding='utf-8'
),
# Python中 os 模块提供的一个函数,用于获取指定路径的文件或目录的详细信息
# os.stat(path).st_size 输出文件大小
# os.stat(path).st_mtime 输出修改时间
# os.stat(path).st_mode 输出权限
os.stat(filepath).st_size
)
# send() 用于发送数据到与给定套接字关联的目标地址
s.send(fhead)
fp = open(filepath, 'rb') # 打开地址路径并以二进制读取
while True:
data = fp.read(1024) # 读入图片数据
if not data:
print('{0} send over……'.format(filepath))
break
s.send(data) # 以二进制格式发送图片数据
s.close() # 关闭套接字
if __name__ == '__main__':
sock_client_image()