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 命令行非阻塞输入的小例子
Sep 27 Python
windows下python模拟鼠标点击和键盘输示例
Feb 28 Python
Python生成验证码实例
Aug 21 Python
python解决js文件utf-8编码乱码问题(推荐)
May 02 Python
Python pymongo模块常用操作分析
Sep 01 Python
浅谈Python批处理文件夹中的txt文件
Mar 11 Python
妙用itchat! python实现久坐提醒功能
Nov 25 Python
如何在python开发工具PyCharm中搭建QtPy环境(教程详解)
Feb 04 Python
Python run()函数和start()函数的比较和差别介绍
May 03 Python
python dict乱码如何解决
Jun 07 Python
python利用xlsxwriter模块 操作 Excel
Oct 14 Python
python利用faker库批量生成测试数据
Oct 15 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
备份mysql数据库的php代码(一个表一个文件)
2010/05/28 PHP
PHP 将数组打乱 shuffle函数的用法及简单实例
2016/06/17 PHP
php简单读取.vcf格式文件的方法示例
2017/09/02 PHP
javascript 贪吃蛇实现代码
2008/11/22 Javascript
JavaScript 自动完成脚本整理(33个)
2009/10/20 Javascript
Firebug 字幕文件JSON地址获取代码
2009/10/28 Javascript
基于JQUERY的多级联动代码
2012/01/24 Javascript
JS幻灯片可循环播放可平滑旋转带滚动导航(自写)
2013/08/05 Javascript
JS判断数组中是否有重复值得三种实用方法
2013/08/16 Javascript
javascript中match函数的用法小结
2014/02/08 Javascript
JS中getYear()和getFullYear()区别分析
2014/07/04 Javascript
使用Browserify配合jQuery进行编程的超级指南
2015/07/28 Javascript
jQuery操作属性和样式详解
2016/04/13 Javascript
jQuery实现table中的tr上下移动并保持序号不变的实例代码
2016/07/11 Javascript
HTML Table 空白单元格补全的简单实现
2016/10/13 Javascript
js制作简单的音乐播放器的示例代码
2017/08/28 Javascript
vue中实现滚动加载更多的示例
2017/11/08 Javascript
Javascript中parseInt的正确使用方式
2018/10/17 Javascript
JS简单判断是否在微信浏览器打开的方法示例
2019/01/08 Javascript
Node.js开发之套接字(socket)编程入门示例
2019/11/05 Javascript
[02:33]DOTA2英雄基础教程 司夜刺客
2013/12/04 DOTA
使用BeautifulSoup爬虫程序获取百度搜索结果的标题和url示例
2014/01/19 Python
新手如何快速入门Python(菜鸟必看篇)
2017/06/10 Python
python对csv文件追加写入列的方法
2019/08/01 Python
关于Python3 类方法、静态方法新解
2019/08/30 Python
Python urlencode和unquote函数使用实例解析
2020/03/31 Python
Melijoe时尚童装德国官网:Melijoe德国
2016/09/03 全球购物
Perfume’s Club意大利官网:欧洲美妆电商
2019/05/03 全球购物
英国购买威士忌网站:Master of Malt
2019/09/26 全球购物
vue+django实现下载文件的示例
2021/03/24 Vue.js
给导游的表扬信
2014/01/10 职场文书
幼儿教师师德承诺书
2014/05/23 职场文书
2014年销售工作总结与计划
2014/12/01 职场文书
使用golang编写一个并发工作队列
2021/05/08 Golang
python使用pywinauto驱动微信客户端实现公众号爬虫
2021/05/19 Python
浅谈Redis缓冲区机制
2022/06/05 Redis