python实现同一局域网下传输图片


Posted in Python onMarch 20, 2020

简述

Python可以通过网络套接字来进行传输图片
这点还是比较有意思的。

下面用TCP来进行实现,适用于Python3

代码功能简述

下面代码

  • 实现了在一个电脑上发送图片(Sender)
  • 实现了在另外一个电脑(也可以是同一个电脑上的不同端口)接受图片(Reciever)
  • 只发一次,然后只收一次
  • 新图片会在旧图片上多一个 “new_”前缀
  • 必须要先开接受者代码才行,之后再启动发送者代码(不然发送者代码会直接被拒绝)
  • 下面是固定了在一个电脑上(看ip地址,下面写的是127.0.0.1,如果是其他电脑就写其他电脑上的ip地址)
  • 另外本程序只能在同一个局域网下使用(就算是广域网上,那就必须要使用广域网的ip地址)

代码

【后附解析】

Sender.py (发送者)

import socket
import os
import sys
import struct


def sock_client():
  try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('127.0.0.1', 6666))
  except socket.error as msg:
    print(msg)
    print(sys.exit(1))

  while True:
    filepath = input('input the file: ')
    # filepath = 'test.png'
    fhead = struct.pack(b'128sl', bytes(os.path.basename(filepath), encoding='utf-8'), os.stat(filepath).st_size)
    s.send(fhead)
    print('client filepath: {0}'.format(filepath))

    fp = open(filepath, 'rb')
    while 1:
      data = fp.read(1024)
      if not data:
        print('{0} file send over...'.format(filepath))
        break
      s.send(data)
    s.close()
    break


if __name__ == '__main__':
  sock_client()

Reciever.py (接受者)

import socket
import os
import sys
import struct


def socket_service():
  try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(('127.0.0.1', 6666))
    s.listen(10)
  except socket.error as msg:
    print(msg)
    sys.exit(1)

  print("Wait")

  while True:
    sock, addr = s.accept()
    deal_data(sock, addr)
    break
  s.close()


def deal_data(sock, addr):
  print("Accept connection from {0}".format(addr))

  while True:
    fileinfo_size = struct.calcsize('128sl')
    buf = sock.recv(fileinfo_size)
    if buf:
      filename, filesize = struct.unpack('128sl', buf)
      fn = filename.decode().strip('\x00')
      new_filename = os.path.join('./', 'new_' + fn)

      recvd_size = 0
      fp = open(new_filename, 'wb')

      while not recvd_size == filesize:
        if filesize - recvd_size > 1024:
          data = sock.recv(1024)
          recvd_size += len(data)
        else:
          data = sock.recv(1024)
          recvd_size = filesize
        fp.write(data)
      fp.close()
    sock.close()
    break


if __name__ == '__main__':
  socket_service()

解析:

发送者代码:

还是先创建TCP套接字,并发起连接:

具体代码如下:

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('127.0.0.1', 6666))
  except socket.error as msg:
    print(msg)
    print(sys.exit(1))

接下来的While循环中,就开始进行图片发送

  • 通过struct库进行打包,然后再用套接字来发送
  • 注意:网络上的有些代码是不能直接用的,比如在这里,就需要把str变成bytes
  • 通过os库来获取文件的基本名(这个是为了避免有些文件中包含具体路径)
  • 通过os库来获取文件的大小(通过文件状态中关于大小的描述中获取到)
fhead = struct.pack(b'128sl', bytes(os.path.basename(filepath), encoding='utf-8'), os.stat(filepath).st_size)
s.send(fhead)

之后再通过二进制方式来获取文件。
然后再发送出去,每次发送固定长度的数据。先读,再判断是否为空,再发送。

接受端:

还是一样,先创建套接字(不过这个需要绑定对应的ip以及端口)
具体代码如下:(这里写的是监听10个套接字对象,但是在我们代码中并没哟用到)

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(('127.0.0.1', 6666))
    s.listen(10)
  except socket.error as msg:
    print(msg)
    sys.exit(1)

之后就进入到循环,来判断,是否获取到sock对象,这里是会进入阻塞状态的。

deal_data中就开始通过连接的对象来获取数据。

一样,还是一个无限循环,但其实本质上还是空的。。。没什么特别的。

之后就是对于传过来的文件名处理一下,这里的这些“128sl”,其实就是一个大小规模(类似于打包的箱子大小的样子)。然后就是得到新的文件名了。
对应的代码如下:

filename, filesize = struct.unpack('128sl', buf)
fn = filename.decode().strip('\x00')
new_filename = os.path.join('./', 'new_' + fn)

之后的recvd_size,其实就是为了来计数的标签
之后就不断地收,边收边写入文件,一直到收完了之后。就关闭掉对应的文件流
最后关闭套接字,退出循环

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python模块学习 filecmp 文件比较
Aug 27 Python
Python中的高级数据结构详解
Mar 27 Python
Python实现将sqlite数据库导出转成Excel(xls)表的方法
Jul 17 Python
Python时间戳使用和相互转换详解
Dec 11 Python
Python 使用with上下文实现计时功能
Mar 09 Python
Python中logging.NullHandler 的使用教程
Nov 29 Python
Python中dict和set的用法讲解
Mar 28 Python
基于Python 中函数的 收集参数 机制
Dec 21 Python
TensorFLow 不同大小图片的TFrecords存取实例
Jan 20 Python
PyCharm+Pipenv虚拟环境开发和依赖管理的教程详解
Apr 16 Python
Python 操作 MySQL数据库
Sep 18 Python
Python random模块的使用示例
Oct 10 Python
python实现udp传输图片功能
Mar 20 #Python
python实现UDP协议下的文件传输
Mar 20 #Python
python实现TCP文件传输
Mar 20 #Python
python实现FTP循环上传文件
Mar 20 #Python
python实现ftp文件传输功能
Mar 20 #Python
Python开发之身份证验证库id_validator验证身份证号合法性及根据身份证号返回住址年龄等信息
Mar 20 #Python
python实现FTP文件传输的方法(服务器端和客户端)
Mar 20 #Python
You might like
学习使用curl采集curl使用方法
2012/01/11 PHP
PHP 数组遍历foreach语法结构及实例
2016/06/13 PHP
Js 本页面传值实现代码
2009/05/17 Javascript
ext combox 下拉框不出现自动提示,自动选中的解决方法
2010/02/24 Javascript
javascript 面向对象的JavaScript类
2010/05/04 Javascript
基于jQuery试卷自动排版系统
2010/07/18 Javascript
js字符串的各种格式的转换 ToString,Format
2011/08/08 Javascript
JavaScript学习笔记(二) js对象
2011/10/25 Javascript
jquery仿京东导航/仿淘宝商城左侧分类导航下拉菜单效果
2013/04/24 Javascript
Javascript 颜色渐变效果的实现代码
2013/10/01 Javascript
浅谈javascript中自定义模版
2015/01/29 Javascript
jquery实现鼠标滑过显示提示框的方法
2015/02/05 Javascript
简介JavaScript中getUTCMonth()方法的使用
2015/06/10 Javascript
jQuery实现简单下拉导航效果
2015/09/07 Javascript
浅析JavaScript回调函数应用
2016/05/22 Javascript
node.js调用Chrome浏览器打开链接地址的方法
2017/05/17 Javascript
Vue.js实现一个todo-list的上移下移删除功能
2017/06/26 Javascript
vue.js或js实现中文A-Z排序的方法
2018/03/08 Javascript
微信小程序地图(map)组件点击(tap)获取经纬度的方法
2019/01/10 Javascript
Vue组件简易模拟实现购物车
2020/12/21 Vue.js
[52:03]DOTA2-DPC中国联赛 正赛 Ehome vs iG BO3 第三场 1月31日
2021/03/11 DOTA
Python计算已经过去多少个周末的方法
2015/07/25 Python
在python中以相同顺序shuffle两个list的方法
2018/12/13 Python
Django2.1集成xadmin管理后台所遇到的错误集锦(填坑)
2018/12/20 Python
PyQt+socket实现远程操作服务器的方法示例
2019/08/22 Python
解决Pytorch 加载训练好的模型 遇到的error问题
2020/01/10 Python
解决Tensorflow 内存泄露问题
2020/02/05 Python
python输出第n个默尼森数的实现示例
2020/03/08 Python
css3的@media属性实现页面响应式布局示例代码
2014/02/10 HTML / CSS
ruby如何进行集成操作?Ruby能进行多重继承吗?
2013/10/16 面试题
解决python 输出到csv 出现多空行的情况
2021/03/24 Python
30年同学聚会感言
2014/01/30 职场文书
领导班子个人对照检查材料(群众路线)
2014/09/26 职场文书
2014年卫生保健工作总结
2014/12/08 职场文书
python cv2图像质量压缩的算法示例
2021/06/04 Python
win11开机发生死循环重启怎么办?win11开机发生死循环重启解决方法
2022/08/05 数码科技