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的ORM中Pony用法
Feb 09 Python
《与孩子一起学编程》python自测题
May 27 Python
解决python读取几千万行的大表内存问题
Jun 26 Python
Python使用一行代码获取上个月是几月
Aug 30 Python
Python django使用多进程连接mysql错误的解决方法
Oct 08 Python
Django实现一对多表模型的跨表查询方法
Dec 18 Python
django之使用celery-把耗时程序放到celery里面执行的方法
Jul 12 Python
Python如何转换字符串大小写
Jun 04 Python
python如何运行js语句
Sep 09 Python
Python中Selenium模块的使用详解
Oct 09 Python
python爬虫中的url下载器用法详解
Nov 30 Python
解决pytorch-gpu 安装失败的记录
May 24 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 小技巧 -- LAST_INSERT_ID
2009/11/24 PHP
php 无极分类(递归)实现代码
2010/01/05 PHP
五款常用mysql slow log分析工具的比较分析
2011/05/22 PHP
onclick与listeners的执行先后问题详细解剖
2013/01/07 Javascript
JQuery异步加载无限下拉框级联功能实现示例
2014/02/19 Javascript
Jquery响应回车键直接提交表单操作代码
2014/07/25 Javascript
浅谈javascript回调函数
2014/12/07 Javascript
轻量级的原生js日历插件calendar.js使用指南
2015/04/28 Javascript
JS实现兼容性好,自动置顶的淘宝悬浮工具栏效果
2015/09/18 Javascript
用JS动态改变表单form里的action值属性的两种方法
2016/05/25 Javascript
Angularjs实现下拉框联动的示例代码
2017/08/22 Javascript
js实现鼠标点击飘爱心效果
2020/08/19 Javascript
[46:20]TFT vs Secret Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
Python实现网络端口转发和重定向的方法
2016/09/19 Python
Python书单 不将就
2017/07/11 Python
Python绘制KS曲线的实现方法
2018/08/13 Python
python实现切割url得到域名、协议、主机名等各个字段的例子
2019/07/25 Python
图文详解Django使用Pycharm连接MySQL数据库
2019/08/09 Python
Python CSV文件模块的使用案例分析
2019/12/21 Python
解决reload(sys)后print失效的问题
2020/04/25 Python
Python爬虫过程解析之多线程获取小米应用商店数据
2020/11/14 Python
使用HTML5中的contentEditable来将多行文本自动增高
2016/03/01 HTML / CSS
英国翻新电子产品购物网站:Tech Trade
2017/12/25 全球购物
后勤副校长自我鉴定
2013/10/13 职场文书
大学生涯自我鉴定
2014/01/16 职场文书
消防战士优秀事迹材料
2014/02/13 职场文书
大学生村官承诺书
2014/03/28 职场文书
党员学习群众路线心得体会
2014/11/04 职场文书
网络营销计划
2015/01/17 职场文书
总经理助理岗位职责
2015/01/31 职场文书
宝宝满月宴答谢词
2015/09/30 职场文书
化工厂员工工作总结
2015/10/15 职场文书
2016猴年开门红标语口号
2015/12/26 职场文书
四年级语文教学反思
2016/03/03 职场文书
JAVA API 实用类 String详解
2021/10/05 Java/Android
Redis全局ID生成器的实现
2022/06/05 Redis