专栏首页python33Python全栈之路系列之基于sock

3Python全栈之路系列之基于sock

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

发布时间:2017年3月16日 00:04 浏览(106) 评论(0) 分类:Python

前言

此处没有前言

----

粘包

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

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

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

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

文件上传

执行结果如下

client.py文件内容

ansheng@Darker:~/socket_file$ cat client.py
#!/usr/bin/env python
# _*_coding:utf-8 _*_

import socket
import os

# 创建一个socket对象
obj = socket.socket()

# 服务端的IP和端口
obj.connect(('127.0.0.1', 6542))

# 用os模块获取要传送的文件总大小
size = os.stat("old_file.txt").st_size

# 把文件总大小发送给服务端
obj.sendall(bytes(str(size), encoding="utf-8"))

# 接受服务端返回的信息
obj.recv(1024)

# 以rb的模式打开一个要发送的文件d
with open("old_file.txt", "rb") as f:

    # 循环文件的所有内容
    for line in f:
        # 发送给服务端
        obj.sendall(line)
        
# 关闭退出
obj.close()

service.py文件内容

ansheng@Darker:~/socket_file$ cat service.py
#!/usr/bin/env python
# _*_coding:utf-8 _*_

import socket

# 创建一个socket对象
sk = socket.socket()
# 允许连接的IP和端口
sk.bind(('127.0.0.1', 6542))
# 最大连接数
sk.listen(5)

while True:
    # 会一直阻塞,等待接收客户端的请求,如果有客户端连接会获取两个值,conn=创建的连接,address=客户端的IP和端口
    conn, address = sk.accept()
    
    # 客户端发送过来的文件大小
    file_size = str(conn.recv(1024),encoding="utf-8")
    
    # 给客户端发送已经收到文件大小
    conn.sendall(bytes("ack", encoding="utf-8"))
    
    # 文件大小转换成int类型
    total_size = int(file_size)
    
    # 创建一个默认的值
    has_recv = 0
    
    # 打开一个新文件,以wb模式打开
    f = open('new_file.txt', 'wb')
    
    # 进入循环
    while True:
    
        # 如果传送过来的大小等于文件总大小,那么就退出
        if total_size == has_recv:
            break
            
        # 接受客户端发送过来的内容
        data = conn.recv(1024)
        
        # 写入到文件当中
        f.write(data)
        
        # 现在的大小加上客户端发送过来的大小
        has_recv += len(data)
        
    # 关闭
    f.close()

#Python全栈之路 #Socket

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python3 socket实现简单

    #!/usr/bin/env python # -- encoding: utf-8 -- ''' @Author : {liush} @License ...

    py3study
  • 第33天 初识socket编程

      MAC:  mac地址是在每一个计算机出厂的时候就会烧录进网卡内的一串数字,用来唯一的表示一台计算机

    py3study
  • 网络编程之socket的运用

    Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在S...

    py3study
  • 30.3. 企业级开发进阶2.3:UDP编程

    回顾TCP协议:一个非常重要的数据传输协议,很多网络协议都是以TCP协议为基础的;TCP协议要求服务器和客户端通过三次握手交互的方式建立可靠的连接,然后再进行数...

    大牧莫邪
  • [PHP]算法-拼接最小字典序的实现

    陶士涵
  • 零基础Python教程036期 如何判断偶数?

    要求:用户输入一个整数,这是数代表随机(随机数范围1-100之间)产生的整数个数,输出结果为,随机产生的数中有几个数为偶数,这些数分别是什么?

    刘金玉编程
  • java基础(八)

    JAVA并不是纯面向对象的语言。Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的。

    Vincent-yuan
  • SAP UI5 Web Component不同React页面的跳转实现

    (1) 从react-router-dom里导入Switch,Route和Redirect组件:

    Jerry Wang
  • Leetcode 167. Two Sum II - Input array is sorted

    版权声明:博客文章都是作者辛苦整理的,转载请注明出处,谢谢! https://blog.cs...

    Tyan
  • MySQL 8.0 首个自适应参数横空出世

    MySQL8.0推出一个号称可以自适应服务器的参数,保证在各种不同的服务器、虚拟机、容器下自动适配服务器资源,让我们一起来看看到底它能做到什么地步。

    沃趣科技

扫码关注云+社区

领取腾讯云代金券