Python网络编程之基于socket实现文件上传

粘包

在实现发送文件功能之前我们先来理解下粘包的问题,下面有两张图,我觉得很清晰的就可以理解到了。

  • 正常情况下发送文件

  1. 第一步: 客户端把获取到的文件总大小(size=65426)先放到缓冲区,然后发送给服务端
  2. 第二步: 此时客户端接收到的文件总大小就是65426
  • 粘包的问题下发送文件

  1. 第一步: 客户端把获取到的文件总大小(size=65426)先放到缓冲区
  2. 第二步: 此时可能由于文件读取太快,导致缓存区的内容还没有发送到服务端,客户端就把读取到的文件内容(hello)也放到缓存区;
  3. 第三步: 然后客户端就把缓存区的全部内容都发送到服务端,那么客户端本来第一次应该接收到的数据室文件大小(size=65426),但实际接收到的数据确实:65426+hello,那么这个流程就是粘包的问题;
  • 解决粘包问题

如果出现粘包的问题,那么传输的数据就有问题了,如何解决这个问题呢?看下图:

  1. 第一步: 客户端把文件大小放到缓冲区
  2. 第二步: 放入缓冲区之后立刻陷入阻塞的状态,登台服务端回复已收到文件大小,此时是不会再向服务端发送任何数据的
  3. 第三步: 缓存区的数据会发送到服务端
  4. 第四步: 服务端接收到客户端发来的文件大小之后立刻回复客户端,说我收到你发过来的文件大小了;

文件上传

执行结果如下

client.py文件内容

  1. [email protected]:~/socket_file$ cat client.py
  2. #!/usr/bin/env python
  3. # _*_coding:utf-8 _*_
  4. import socket
  5. import os
  6. # 创建一个socket对象
  7. obj = socket.socket()
  8. # 服务端的IP和端口
  9. obj.connect((‘127.0.0.1‘, 6542))
  10. # 用os模块获取要传送的文件总大小
  11. size = os.stat("old_file.txt").st_size
  12. # 把文件总大小发送给服务端
  13. obj.sendall(bytes(str(size), encoding="utf-8"))
  14. # 接受服务端返回的信息
  15. obj.recv(1024)
  16. # 以rb的模式打开一个要发送的文件d
  17. with open("old_file.txt", "rb") as f:
  18.    # 循环文件的所有内容
  19.    for line in f:
  20.        # 发送给服务端
  21.        obj.sendall(line)
  22. # 关闭退出
  23. obj.close()

service.py文件内容

  1. [email protected]:~/socket_file$ cat service.py
  2. #!/usr/bin/env python
  3. # _*_coding:utf-8 _*_
  4. import socket
  5. # 创建一个socket对象
  6. sk = socket.socket()
  7. # 允许连接的IP和端口
  8. sk.bind((‘127.0.0.1‘, 6542))
  9. # 最大连接数
  10. sk.listen(5)
  11. while True:
  12.    # 会一直阻塞,等待接收客户端的请求,如果有客户端连接会获取两个值,conn=创建的连接,address=客户端的IP和端口
  13.    conn, address = sk.accept()
  14.    # 客户端发送过来的文件大小
  15.    file_size = str(conn.recv(1024),encoding="utf-8")
  16.    # 给客户端发送已经收到文件大小
  17.    conn.sendall(bytes("ack", encoding="utf-8"))
  18.    # 文件大小转换成int类型
  19.    total_size = int(file_size)
  20.    # 创建一个默认的值
  21.    has_recv = 0
  22.    # 打开一个新文件,以wb模式打开
  23.    f = open(‘new_file.txt‘, ‘wb‘)
  24.    # 进入循环
  25.    while True:
  26.        # 如果传送过来的大小等于文件总大小,那么就退出
  27.        if total_size == has_recv:
  28.            break
  29.        # 接受客户端发送过来的内容
  30.        data = conn.recv(1024)
  31.        # 写入到文件当中
  32.        f.write(data)
  33.        # 现在的大小加上客户端发送过来的大小
  34.        has_recv += len(data)
  35.    # 关闭
  36.    f.close()
时间: 2024-12-15 06:45:53

Python网络编程之基于socket实现文件上传的相关文章

3Python全栈之路系列之基于socket实现文件上传

Python全栈之路系列之基于socket实现文件上传 发布时间:2017年3月16日 00:04 浏览(106) 评论(0) 分类:Python 前言 此处没有前言 粘包 在实现发送文件功能之前我们先来理解下粘包的问题,下面有两张图,我觉得很清晰的就可以理解到了. 正常情况下发送文件 第一步: 客户端把获取到的文件总大小(size=65426)先放到缓冲区,然后发送给服务端 第二步: 此时客户端接收到的文件总大小就是65426 粘包的问题下发送文件 第一步: 客户端把获取到的文件总大小(siz

java网络编程(7)——利用tcp实现文件上传

其实客户端与服务端通讯的道理都是一样的,都是通过输入与输出这两个流,那么实现文件上传也就是同样的,客户端把文件读到文件流,服务端用文件流来接受,然后写到一个文件中,这样子就实现了文件上传,文件拷贝也是同样的道理~,具体看代码实现: 客户端: package com.seven.tcp; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStre

Python网络编程之基于socket实现聊天机器人

通过socket实现局域网内的聊天工具. service.py文件如下: #!/usr/bin/env python # _*_ coding:utf-8 _*_ import socket # 创建一个socket对象 sk = socket.socket() # 绑定允许连接的IP地址和端口 sk.bind(('127.0.0.1', 6053, )) # 服务端允许起来之后,限制客户端连接的数量,如果超过五个连接,第六个连接来的时候直接断开第六个. sk.listen(5) while T

Python网络编程02/基于TCP协议的socket简单的通信

目录 Python网络编程02/基于TCP协议的socket简单的通信 1.昨日内容回顾 2.socket 2.1 socket套接字 2.2 基于TCP协议的socket简单通信 Python网络编程02/基于TCP协议的socket简单的通信 1.昨日内容回顾 1.单播:单独联系某一个人 2.广播:给所有人发送消息(群发) 3.比特流:bit就是0101跟水流一样的源源不断的发送01010101 4.以太网协议:将数据进行分组:一组称之为一帧,数据报 head|data head:18字节:

Socket大文件上传

1 public sealed class SocketData 2 { 3 private SocketData() 4 { 5 } 6 7 public static SendFileMode SendFile(Socket socket, string fileName, int maxBufferLength) 8 { 9 SendFileMode flag = SendFileMode.Success; 10 try 11 { 12 using (Stream fs = new Fil

SpringMVC经典系列-12基于SpringMVC的文件上传---【LinusZhu】

注意:此文章是个人原创,希望有转载需要的朋友们标明文章出处,如果各位朋友们觉得写的还好,就给个赞哈,你的鼓励是我创作的最大动力,LinusZhu在此表示十分感谢,当然文章中如有纰漏,请联系[email protected],敬请朋友们斧正,谢谢. 不知不觉已经把Spring的基础部分讲解完了,所讲述的都是在项目中经常用到的东西,是经得住考验的,接下来的部分主要是要讲述使用SpringMVC进行的文件上传.处理Ajax请求.自定义拦截器功能的实现,不多说了,首先讲解文件上传部分,开始--     

Android开发之网络请求通信专题(二):基于HttpClient的文件上传下载

上一篇专题Android开发之网络请求通信专题(一):基于HttpURLConnection的请求通信我们讲解了如何使用httpurlconnection来实现基本的文本数据传输.一般在实际开发中我们可以用于传输xml或者json格式的数据.今天我们来讲解另外一种http网络请求的方式:httpclient,并实现文件的上传和下载. 在这里插个题外话,其实这些网络请求有很多第三方jar包可以使用,这些包都封装得很好了.如果只是想使用,我们就直接拿别人得jar包来用就好.博主这里推荐一个叫xuti

iOS开发之网络编程--5、NSURLSessionUploadTask+NSURLSessionDataDelegate代理上传

前言:关于NSURLSession的主要内容快到尾声了,这里就讲讲文件上传.关于文件上传当然就要使用NSURLSessionUploadTask,这里直接讲解常用的会和代理NSURLSessionDataDelegate一起搭配实现文件上传功能.另外,下面使用的文件上传思路是和NSURLConnection中本人之前的随笔<iOS开发之网络编程--使用NSURLConnection实现文件上传>提到的上传思路是一样的,都是要将请求信息拼接起来,然后传入到请求里进行上传.这个拼接过程是必要的,但

Servlet基于HttpServletRequestWrapper的文件上传

在使用servlet上传的时候,因为request里面有时候既包含了参数信息还有文件信息,取出来的时候就会很麻烦,所以我们可以根据request取出参数的原理,相当于自定义一个request来实现我们的文件上传和其他参数取出的分离. 一.关联关系和依赖关系 介绍这个问题之前,需要先理解几个概念 关联关系 用下面简单代码解释,也就是A里面包含一个B的实例 Class A{ private B b; } 依靠关系 用下面代码解释就是A中的方法需要B类的作为参数参与 Class A{ public v