IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python使用socket高效传输视频数据帧(连续发送图片) -> 正文阅读

[Python知识库]python使用socket高效传输视频数据帧(连续发送图片)

遇到的问题

网上找了一些代码,都是只能建立一次socket传输一张图片,然后断开重新连重新传。而建立一次socket代价不小,反复建立会非常消耗系统资源,因此尝试自己通过一次socket连续传输多张图片

代码问题记录(需要代码的可以直接文末)

在做的过程中发现了一些问题:

  1. socket在传一张图片时是以二进制流的形式传输,图片的二进制流比较大,一般一次传不完,要传很多次。那么接受者是如何知道什么时候才停止接收这张图片呢?那可以让发送者在发图之前先发一个头信息,告诉接收者这个二进制流有多长,然后接收者通过这个来判断是否传完。
  2. 这个问题是最让我致命的,由于发送者先发了一个头信息,使用socket.send()函数,然后发送图片也是要用socket.send()函数,接收端使用的是socket.recv(1024)函数,1024是缓存大。麻烦来了,由于发送者使用连续的两个send,而socket.recv(1024)是有缓存的,他会把这两个信息缓存到一起去,信息头和图片信息全被缓存了!!!这会直接导致代码接收逻辑错误。我的做法是,不能有两个send同时出现,那么我就在send中间加一个recv函数(阻塞函数),也就是发送者每发一个消息,接收者就立马回复一个消息,这样就保证了不会连续send在这里插入图片描述

代码

由于项目存在两种数据源,一种是可见光,一种是红外,所以我最开始还要制作一个信息头,每次发送的时候要告诉接收者这是什么类型的数据,然后再接收

制作不易,记得给个赞哈!

客户端clien.py

# 服务器的地址
server_address = ('127.0.0.1', 8000)


def send(dir_name, data_format, file_name):
    # 与接收端建立socket通信
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # AF_INET(TCP/IP – IPv4)协议
    sock.connect(server_address)

    # 每次通信都带一个通信头,表明数据源的类型(红外还是可见光),要保存数据帧的文件夹名file_name
    # 你可以不要数据格式,这里可以定义成你自己的形式,也算是一种安全机制
    sock.send('{}|{}'.format(data_format, file_name).encode())  # 默认编码 utf-8,发送文件长度和文件名
    reply = sock.recv(1024)

    # 按照文件名排序,0.png,1.png
    file_list = os.listdir(dir_name)
    file_list.sort(key=lambda x: int(x[:-4]))
    if 'ok' == reply.decode():  # 确认一下服务器get到文件长度和文件名数据
        i = 0
        print(len(file_list))
        for file_name in file_list:
            data = file_deal(os.path.join(dir_name, file_name))
            sock.send('{}|{}'.format(len(data), file_name).encode())
            sock.recv(1024)
            go = 0
            total = len(data)
            while go < total:  # 发送文件
                data_to_send = data[go:go + total//2]
                sock.send(data_to_send)
                go += len(data_to_send)
            sock.recv(1024).decode()
            i += 1
            if i < len(file_list):
                sock.send(b'continue')
        sock.send(b'over')
        sock.close()
        sys.exit(0)


def file_deal(file_path):  # 读取文件的方法
    mes = b''
    try:
        file = open(file_path, 'rb')
        mes = file.read()
    except:
        print('error{}'.format(file_path))
    else:
        file.close()
        return mes

服务端server.py

LOCAL_IP = '127.0.0.1'  # 本机测试使用ip,局域网中使用需更换ip
PORT = 8000  # 随意指定一个端口

def server():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # socket.AF_INET 指ipv4  socket.SOCK_STREAM 使用tcp协议
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 设置端口
    sock.bind((LOCAL_IP, PORT))  # 绑定端口
    sock.listen(3)  # 监听端口
    while True:
        sc, sc_name = sock.accept()  # 当有请求到指定端口是 accept()会返回一个新的socket和对方主机的(ip,port)
        print('收到{}机器请求'.format(sc_name))
        info = sc.recv(1024)  # 接受客户端发来的协议头,区分数据源
        # 安全处理:如果不是以这个协议头开始,认为是非法接入,就直接断掉。这里可以自己定义一些安全消息机制
        print(info)
        try:
            data_format, directory_name = info.decode().split("|")
            sc.send(b'ok')  # 表示收到文件长度和文件名
        except:
            print('协议头不对,自动断开连接')
            sc.close()
            continue

        if not os.path.exists(directory_name):
            os.mkdir(directory_name)
        # 协议头正确之后,不断接收发来的数据帧
        while True:
            head_info = sc.recv(1024)
            # print(data_info)
            length, file_name = head_info.decode().split('|')
            sc.send(b'ok')
            if length and file_name:
                print(file_name)
                newfile = open(os.path.join(directory_name, file_name), 'wb')  # 这里可以使用从客户端解析出来的文件名
                file = b''
                total = int(length)
                get = 0
                while get < total:  # 接收文件
                    data = sc.recv(total//2)
                    file += data
                    get = get + len(data)
                sc.send(b'ok')
                print('应该接收{},实际接收{}'.format(length, len(file)))
                if file:
                    print('actually length:{}'.format(len(file)))
                    newfile.write(file[:])
                    newfile.close()
            reply = sc.recv(1024)
            if reply.decode() == "over":
                break

server()

参考文章

https://blog.csdn.net/hfutzhouyonghang/article/details/86624684

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-10-21 12:08:59  更:2021-10-21 12:10:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 10:38:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计