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编程中time模块的使用
Nov 20 Python
python实现聚类算法原理
Feb 12 Python
python生成不重复随机数和对list乱序的解决方法
Apr 09 Python
Python读取数据集并消除数据中的空行方法
Jul 12 Python
详解Python requests 超时和重试的方法
Dec 18 Python
python 对类的成员函数开启线程的方法
Jan 22 Python
python脚本后台执行方式
Dec 21 Python
python实现双色球随机选号
Jan 01 Python
Python调用钉钉自定义机器人的实现
Jan 03 Python
Python3如何在Windows和Linux上打包
Feb 25 Python
django在开发中取消外键约束的实现
May 20 Python
Python json解析库jsonpath原理及使用示例
Nov 25 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 日志缩略名的创建函数代码
2010/05/26 PHP
PHP5 的对象赋值机制介绍
2011/08/02 PHP
php防止sql注入示例分析和几种常见攻击正则表达式
2014/01/12 PHP
PHP和javascript常用正则表达式及用法实例
2014/07/01 PHP
php获取本周星期一具体日期的方法
2015/04/20 PHP
PHP请求Socket接口测试实例
2016/08/12 PHP
TP5框架安全机制实例分析
2020/04/05 PHP
javascript之解决IE下不渲染的bug
2007/06/29 Javascript
jQuery+.net实现浏览更多内容(改编php版本)
2013/03/28 Javascript
iframe如何动态创建及释放其所占内存
2014/09/03 Javascript
JS获取图片lowsrc属性的方法
2015/04/01 Javascript
AngularJs Forms详解及简单示例
2016/09/01 Javascript
JavaScript编写九九乘法表(两种任选)
2017/02/04 Javascript
解决layui中table异步数据请求不支持自定义返回数据格式的问题
2018/08/19 Javascript
详解微信小程序与内嵌网页交互实现支付功能
2018/10/22 Javascript
微信小程序下拉菜单效果的实例代码
2019/05/14 Javascript
JS实现可用滑块滑动的缓动图代码
2019/09/01 Javascript
Vue解析剪切板图片并实现发送功能
2020/02/04 Javascript
浅谈element中InfiniteScroll按需引入的一点注意事项
2020/06/05 Javascript
如何在面试中手写出javascript节流和防抖函数
2020/10/22 Javascript
[02:49]2014DOTA2电竞也是体育项目! 势要把荣誉带回中国!
2014/07/20 DOTA
Python 专题三 字符串的基础知识
2017/03/19 Python
python实现的二叉树定义与遍历算法实例
2017/06/30 Python
python 获取url中的参数列表实例
2018/12/18 Python
PyCharm在新窗口打开项目的方法
2019/01/17 Python
Pycharm简单使用教程(入门小结)
2019/07/04 Python
旅游市场营销方案
2014/03/09 职场文书
抗震救灾标语
2014/06/26 职场文书
行政管理专业求职信
2014/07/06 职场文书
处级干部反四风个人对照检查材料思想汇报
2014/09/27 职场文书
2015年党员自评材料
2014/12/17 职场文书
2015年感恩节演讲稿(优选篇)
2015/03/20 职场文书
历史博物馆观后感
2015/06/05 职场文书
我的兄弟姐妹观后感
2015/06/15 职场文书
导游词之上海东方明珠塔
2019/09/25 职场文书
Python进阶学习之带你探寻Python类的鼻祖-元类
2021/05/08 Python