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 相关文章推荐
基于scrapy实现的简单蜘蛛采集程序
Apr 17 Python
Python编写生成验证码的脚本的教程
May 04 Python
Python创建xml文件示例
Mar 22 Python
Window 64位下python3.6.2环境搭建图文教程
Sep 19 Python
对Python中for复合语句的使用示例讲解
Nov 01 Python
10款最好的Python开发编辑器
Jul 03 Python
wxpython布局的实现方法
Nov 01 Python
pytorch实现保证每次运行使用的随机数都相同
Feb 20 Python
python 安装impala包步骤
Mar 28 Python
Python Selenium实现无可视化界面过程解析
Aug 25 Python
python基于exchange函数发送邮件过程详解
Nov 06 Python
pytorch中的model.eval()和BN层的使用
May 22 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
Zend Framework开发入门经典教程
2016/03/23 PHP
PHP PDOStatement::bindValue讲解
2019/01/30 PHP
laravel框架使用FormRequest进行表单验证,验证异常返回JSON操作示例
2020/02/18 PHP
几款极品的javascript压缩混淆工具
2007/05/16 Javascript
浏览器无法运行JAVA脚本的解决方法
2008/01/09 Javascript
window.onload 加载完毕的问题及解决方案(下)
2009/07/09 Javascript
javascript下判断一个元素是否存在的代码
2010/03/05 Javascript
jquery和javascript的区别(常用方法比较)
2013/07/04 Javascript
javascript中数组的冒泡排序使用示例
2013/12/18 Javascript
Javascript 完美运动框架(逐行分析代码,让你轻松了运动的原理)
2015/01/23 Javascript
JS或jQuery获取ASP.NET服务器控件ID的方法
2015/06/08 Javascript
jquery+php随机生成红包金额数量代码分享
2015/08/27 Javascript
使用canvas实现仿新浪微博头像截取上传功能
2015/09/02 Javascript
jquery实现表单验证简单实例演示
2015/11/23 Javascript
JS面向对象编程详解
2016/03/06 Javascript
关于Vue Webpack2单元测试示例详解
2017/08/14 Javascript
JavaScript贪吃蛇小组件实例代码
2017/08/20 Javascript
Vue DevTools调试工具的使用
2017/12/05 Javascript
在js代码拼接dom对象到页面上的模板总结
2018/10/21 Javascript
js仿360开机效果
2019/12/26 Javascript
Node.js API详解之 vm模块用法实例分析
2020/05/27 Javascript
Python中实现参数类型检查的简单方法
2015/04/21 Python
ubuntu 18.04 安装opencv3.4.5的教程(图解)
2019/11/04 Python
Python object类中的特殊方法代码讲解
2020/03/06 Python
python多线程实现同时执行两个while循环的操作
2020/05/02 Python
python_matplotlib改变横坐标和纵坐标上的刻度(ticks)方式
2020/05/16 Python
python字典通过值反查键的实现(简洁写法)
2020/09/30 Python
python的scipy.stats模块中正态分布常用函数总结
2021/02/19 Python
DIY蛋糕店的创业计划书范文
2013/12/26 职场文书
促销活动总结范文
2014/04/30 职场文书
家长学校工作方案
2014/05/07 职场文书
街道党工委党的群众路线教育实践活动对照检查材料思想汇报
2014/10/05 职场文书
吃空饷专项整治方案
2014/10/27 职场文书
2014年健康教育工作总结
2014/11/20 职场文书
2016年三八节红领巾广播稿
2015/12/17 职场文书
Python中 range | np.arange | np.linspace三者的区别
2022/03/22 Python