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自动化测试之从命令行运行测试用例with verbosity
Sep 28 Python
Python中使用异常处理来判断运行的操作系统平台方法
Jan 22 Python
Python的动态重新封装的教程
Apr 11 Python
python实现随机森林random forest的原理及方法
Dec 21 Python
Python使用OpenCV进行标定
May 08 Python
python利用tkinter实现屏保
Jul 30 Python
Python Scrapy框架:通用爬虫之CrawlSpider用法简单示例
Apr 11 Python
Python连接Hadoop数据中遇到的各种坑(汇总)
Apr 14 Python
基于python SMTP实现自动发送邮件教程解析
Jun 02 Python
Python pysnmp使用方法及代码实例
Aug 24 Python
python中的split、rsplit、splitlines用法说明
Oct 23 Python
python图像处理基本操作总结(PIL库、Matplotlib及Numpy)
Jun 08 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中几个可以提高运行效率的代码写法、技巧分享
2014/08/21 PHP
php字符串过滤与替换小结
2015/01/26 PHP
Zend Framework实现多服务器共享SESSION数据的方法
2016/03/22 PHP
PHP基于SimpleXML生成和解析xml的方法示例
2017/07/17 PHP
jQuery Flash/MP3/Video多媒体插件
2010/01/18 Javascript
JavaScript中的onerror事件概述及使用
2013/04/01 Javascript
使用CSS3的scale实现网页整体缩放
2014/03/18 Javascript
jQuery实现文本框输入同步的方法
2015/06/20 Javascript
强大Vue.js组件浅析
2016/09/12 Javascript
浅谈Koa2框架利用CORS完成跨域ajax请求
2018/03/06 Javascript
详解jQuery中的easyui
2018/09/02 jQuery
layui 上传插件 带预览 非自动上传功能的实例(非常实用)
2019/09/23 Javascript
js判断非127开头的IP地址的实例代码
2020/01/05 Javascript
Scrapy-redis爬虫分布式爬取的分析和实现
2017/02/07 Python
Linux下python与C++使用dlib实现人脸检测
2018/06/29 Python
Python 微信爬虫完整实例【单线程与多线程】
2019/07/06 Python
python 模拟创建seafile 目录操作示例
2019/09/26 Python
使用python绘制cdf的多种实现方法
2020/02/25 Python
Python递归函数特点及原理解析
2020/03/04 Python
Django用数据库表反向生成models类知识点详解
2020/03/25 Python
Python函数必须先定义,后调用说明(函数调用函数例外)
2020/06/02 Python
python实现发送带附件的邮件代码分享
2020/09/22 Python
利用CSS3动画实现圆圈由小变大向外扩散的效果实例
2018/09/10 HTML / CSS
美国第一香水网站:Perfume.com
2017/01/23 全球购物
新西兰第一的行李箱网站:luggage.co.nz
2019/07/22 全球购物
简单叙述一下MYSQL的优化
2016/05/09 面试题
旷课检讨书3000字
2014/02/04 职场文书
小学毕业感言150字
2014/02/05 职场文书
经典广告词大全
2014/03/14 职场文书
申论倡议书范文
2014/05/13 职场文书
个人自荐材料
2014/05/23 职场文书
大学英语专业求职信
2014/06/21 职场文书
工伤私了协议书范本
2014/11/24 职场文书
婚礼嘉宾致辞
2015/07/28 职场文书
2016领导干部廉洁从政心得体会
2016/01/19 职场文书
Python内置包对JSON文件数据进行编码和解码
2022/04/12 Python