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去除列表中重复元素的方法
Mar 20 Python
对于Python的Django框架部署的一些建议
Apr 09 Python
python机器人行走步数问题的解决
Jan 29 Python
Window 64位下python3.6.2环境搭建图文教程
Sep 19 Python
Python mutiprocessing多线程池pool操作示例
Jan 30 Python
django框架面向对象ORM模型继承用法实例分析
Jul 29 Python
Python使用scipy模块实现一维卷积运算示例
Sep 05 Python
python实现对列表中的元素进行倒序打印
Nov 23 Python
PyTorch中topk函数的用法详解
Jan 02 Python
TENSORFLOW变量作用域(VARIABLE SCOPE)
Jan 10 Python
Python 字节流,字符串,十六进制相互转换实例(binascii,bytes)
May 11 Python
用python写PDF转换器的实现
Oct 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 中的输出缓冲
2006/12/21 PHP
PHP常用特殊运算符号和函数总结(php新手入门必看)
2013/02/02 PHP
PHP调用VC编写的COM组件实例
2014/03/29 PHP
php smarty模板引擎的6个小技巧
2014/04/24 PHP
PHP延迟静态绑定示例分享
2014/06/22 PHP
PHP curl模拟登录带验证码的网站
2015/11/30 PHP
Laravel 5+ .env环境配置文件详解
2020/04/06 PHP
JS代码格式化和语法着色V2
2006/10/14 Javascript
javascript动画效果类封装代码
2007/08/28 Javascript
mapper--图片热点区域高亮组件官方站点
2007/12/22 Javascript
JS 无法通过W3C验证的处理方法
2010/03/09 Javascript
JavaScript中json对象和string对象之间相互转化
2012/12/26 Javascript
document.forms用法示例介绍
2014/06/26 Javascript
js css 实现遮罩层覆盖其他页面元素附图
2014/09/22 Javascript
jQuery对象的length属性用法实例
2014/12/27 Javascript
js中实现字符串和数组的相互转化详解
2016/01/24 Javascript
JS使用Dijkstra算法求解最短路径
2019/01/17 Javascript
微信小程序Page中data数据操作和函数调用方法
2019/05/08 Javascript
JavaScript oncopy事件用法实例解析
2020/05/13 Javascript
11个Javascript小技巧帮你提升代码质量(小结)
2020/12/28 Javascript
[51:53]完美世界DOTA2联赛循环赛 LBZS vs DM BO2第二场 11.01
2020/11/02 DOTA
Python Mysql数据库操作 Perl操作Mysql数据库
2009/01/12 Python
使用python Django做网页
2013/11/04 Python
python中的五种异常处理机制介绍
2014/09/02 Python
浅谈Python里面小数点精度的控制
2018/07/16 Python
python读取txt文件中特定位置字符的方法
2018/12/24 Python
Python实现FM算法解析
2019/06/18 Python
基于python3 的百度图片下载器的实现代码
2019/11/05 Python
Python for i in range ()用法详解
2020/09/18 Python
python+django+selenium搭建简易自动化测试
2020/08/19 Python
信息工程学院毕业生推荐信
2013/11/05 职场文书
《放飞蜻蜓》教学反思
2014/04/27 职场文书
责任胜于能力演讲稿
2014/05/20 职场文书
食品安全标语
2014/06/07 职场文书
市场营销计划书范文
2015/01/16 职场文书
2019开业庆典剪彩仪式主持词!
2019/07/22 职场文书