python socket通信传输图片源码分析

一、业务逻辑        

        客服端与服务端创立连接后,客服端发送目录下图片名,图片通过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()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值