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 相关文章推荐
使用httplib模块来制作Python下HTTP客户端的方法
Jun 19 Python
浅谈Python 对象内存占用
Jul 15 Python
聊聊Python中的pypy
Jan 12 Python
python+opencv实现霍夫变换检测直线
Oct 23 Python
提升Python程序性能的7个习惯
Apr 14 Python
详解Python爬取并下载《电影天堂》3千多部电影
Apr 26 Python
python中将两组数据放在一起按照某一固定顺序shuffle的实例
Jul 15 Python
详解用Python为直方图绘制拟合曲线的两种方法
Aug 21 Python
Python操作多维数组输出和矩阵运算示例
Nov 28 Python
Python Numpy,mask图像的生成详解
Feb 19 Python
python中线程和进程有何区别
Jun 17 Python
python ssh 执行shell命令的示例
Sep 29 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
PHP 循环列出目录内容的函数代码
2010/05/26 PHP
ThinkPHP路由机制简介
2016/03/23 PHP
js 多浏览器分别判断代码
2010/04/01 Javascript
分享两个手机访问pc网站自动跳转手机端网站代码
2020/12/24 Javascript
SVG动画vivus.js库使用小结(实例代码)
2017/09/14 Javascript
微信小程序使用Socket的实例
2017/09/19 Javascript
vue2 router 动态传参,多个参数的实例
2017/11/10 Javascript
js 判断一个数字是不是2的n次方幂的实例
2017/11/26 Javascript
基于JS实现html中placeholder属性提示文字效果示例
2018/04/19 Javascript
微信小程序使用form表单获取输入框数据的实例代码
2018/05/17 Javascript
微信小程序实现团购或秒杀批量倒计时
2020/11/01 Javascript
浅谈TypeScript的类型保护机制
2020/02/23 Javascript
[02:09]DOTA2辉夜杯 EHOME夺冠举杯现场
2015/12/28 DOTA
python实现的登录和操作开心网脚本分享
2014/07/09 Python
python映射列表实例分析
2015/01/26 Python
python实现自动获取IP并发送到邮箱
2018/12/26 Python
基于python历史天气采集的分析
2019/02/14 Python
Python 调用 Outlook 发送邮件过程解析
2019/08/08 Python
redis数据库及与python交互用法简单示例
2019/11/01 Python
6行Python代码实现进度条效果(Progress、tqdm、alive-progress​​​​​​​和PySimpleGUI库)
2020/01/06 Python
python 微信好友特征数据分析及可视化
2020/01/07 Python
Python图像识别+KNN求解数独的实现
2020/11/13 Python
伯利陶器:Burleigh Pottery
2018/01/03 全球购物
科茨沃尔德家居商店:Scotts of Stow
2018/06/29 全球购物
IFCHIC台湾:欧美国际设计师品牌
2019/05/18 全球购物
设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。
2014/12/30 面试题
4s店机修工岗位职责
2013/12/20 职场文书
刘胡兰的英雄事迹材料
2014/02/11 职场文书
党员违纪检讨书
2014/02/18 职场文书
家长对学生的评语
2014/04/18 职场文书
我的梦中国梦演讲稿
2014/04/23 职场文书
女生抽烟检讨书
2014/10/05 职场文书
2015社区个人工作总结范文
2015/05/13 职场文书
2016年学校十一国庆节活动总结
2016/04/01 职场文书
简历自我评价:教师师德表现自我评价
2019/04/24 职场文书
启动Tomcat时出现大量乱码的解决方法
2021/06/21 Java/Android