• 网络基础补充,断点续传,以及如何添加进度条


    一丶网络基础补充

      端口:

        端口是为了将同一个电脑上的不同程序进行隔离,

        每一个程序都有一个自己的端口,程序通过自己的那个端口来进行一些操作如:

           MySQL是一个软件,软件帮助我们在硬盘上进行文件操作。默认端口:3306

           Redis是一个软件,软件帮助我们在内存里进行数据操作。默认端口:6379

           网站默认端口:80 ,访问时:http://www.luffycity.com:80

        网站默认端口:443 ,访问时:https://www.luffycity.com:443  


      OSI七层模型  

        人们按照分工不同把互联网协议从逻辑上划分了层级:

     

      第一层: 物理层
        主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的模数转换与数模转换)。这一层的数据叫做比特。

      第二层: 数据链路层
        主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。
      
      第三层: 网络层
        主要将从下层接收到的数据进行IP地址(例192.168.0.1)的封装与解封装。在这一层工作的设备是路由器,常把这一层的数据叫做数据包。 
      
      第四层: 传输层
        定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。 主要是将从下层接收的数据进行分段进行传输,到达目的地址后在进行重组。常常把这一层数据叫做段。

      第五层: 会话层
        通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)
        
      第六层: 表示层
        主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够能识别的东西(如图片、声音等))

      第七层: 应用层
        主要是一些终端的应用,比如说FTP(各种文件下载),WEB(IE浏览),QQ之类的(你就把它理解成我们在电脑屏幕上可以看到的东西.就 是终端应用)。
        

      TCP三次握手与四次挥手:

        TCP建立连接为什么是三次握手,而不是两次或四次?

        TCP,名为传输控制协议,是一种可靠的传输层协议,IP协议号为6。

        顺便说一句,原则上任何数据传输都无法确保绝对可靠,三次握手只是确保可靠的基本需要。

        举个日常例子,打电话时我们对话如下:

        对应的客户端与服务端如下:

       四次挥手:

          先由客户端向服务器端发送一个FIN,请求关闭数据传输。

          当服务器接收到客户端的FIN时,向客户端发送一个ACK,其中ack的值等于FIN+SEQ

          然后服务器向客户端发送一个FIN,告诉客户端应用程序关闭。

          当客户端收到服务器端的FIN是,回复一个ACK给服务器端。其中ack的值等于FIN+SEQ

     我们为什么要四次挥手呢?   

           确保数据能够完整传输

          当被动方收到主动方的FIN报文通知时,它仅仅表示主动方没有数据再发送给被动方了.

          但未必被动方所有的数据都完整的发送给了主动方,所以被动方不会马上关闭SOCKET,它可能还需要发送一些数据给主动方后,

         再发送FIN报文给主动方,告诉主动方同意关闭连接,所以这里的ACK报文和FIN报文多数情况下都是分开发送的

    二丶断点续传

    服务端:

    import socketserver
    import hashlib
    import json
    import struct
    import os
    
    
    class Myserver(socketserver.BaseRequestHandler):
        def handle(self):
            while 1:
                print("等待用户输入....")
                num = self.request.recv(8096).decode("utf8")
                num = int(num)
                if num == 1:        #接收文件
                    md5 = hashlib.md5()
                    file_info_json = self.request.recv(8096)
                    file_info = json.loads(file_info_json)
    
                    filename = file_info.get("filename")
                    file_size = file_info.get("file_size")
    
                    if os.path.isfile("put/" + "%s副本" % filename):  # 如果是存在的文件,返回True.否则返回False)
                        filename_size = os.path.getsize("put/" + "%s副本" % filename)  # 返回path的大小
                    else:
                        filename_size = 0
    
                    filename_size_struct = struct.pack("i", filename_size)
                    self.request.send(filename_size_struct)  # 发送文件大小
    
                    # 循环接收文件
                    with open("put/" + "%s副本" % filename, "ab") as f:
                        while filename_size < file_size:
                            data = self.request.recv(8096)
                            filename_size += len(data)
                            f.write(data)
                            # MD5摘要
                            md5.update(data)  # 写入要加密的的东西
                            # print("文件总大小:%s,已成功接收%s" % (filesize, recv_data_length))
    
                    self.request.send(b"OK")
                    md5_val = md5.hexdigest()  # 解密
                    client_md5 = self.request.recv(8096).decode('utf8')
                    if md5_val == client_md5:
                        self.request.send(b"203")
                        print("接收成功!")
                        os.rename("put/" + "%s副本" % filename, "put/" + filename)
                        break
                    # else:
                    #     self.request.send(b"204")
                    #     print("接收失败!")
    
    
                elif num == 2:      #发送文件
                    file_info_json = self.request.recv(8096)
                    file_info = json.loads(file_info_json)
    
                    filename = file_info.get("filename")
                    filename_size = file_info.get("filename_size")
    
                    filesize = os.path.getsize("put/" + filename)
                    filesize = struct.pack("i", filesize)
                    self.request.send(filesize)  #发送文件大小
    
                    md5 = hashlib.md5()
                    with open("put/" + filename,"rb") as f:
                        f.seek(filename_size)
                        for line in f:
                            self.request.send(line)
                            md5.update(line)  # 写入要加密的东西
    
                    data = self.request.recv(8096)
                    md5_val = md5.hexdigest()  # 获取密文
                    self.request.send(md5_val.encode("utf8"))
                    is_valid = self.request.recv(8096).decode("utf8")
                    if is_valid == "203":
                        print("传递成功,文件完整!")
                        break
                    else:
                        print("文件上传失败!")
                        break
    
    server = socketserver.ThreadingTCPServer(("192.168.13.226",8080),Myserver)
    
    server.serve_forever()
    服务端

    客户端:

    import socket
    import os
    import json
    import struct
    import hashlib
    
    sock = socket.socket()
    sock.connect(("192.168.13.226",8080))
    md5 = hashlib.md5()
    
    while 1:
        num = input("1.上传 2.下载")
        sock.send(num.encode("utf8"))
        num = int(num)
        if num == 1:
            filename = input("请输入要上传的文件名:")
            file_size = os.path.getsize("put/" +filename)
            file_info = {
                "filename": filename,
                "file_size": file_size,
            }
            file_info_json = json.dumps(file_info).encode("utf8")  # 将字典序列化
            sock.send(file_info_json)
    
            filename_size = sock.recv(8096)
            filename_size = struct.unpack("i", filename_size)[0]  # 解包
            if filename_size != 0:
                row1 = input("文件还未下载完毕,是否续传?(1&2)")
                if row1 == "2":
                    filename_size = 0
    
            #循环上传
            md5 = hashlib.md5()
            with open("put/" + filename, "rb") as f:
                f.seek(filename_size)
                for line in f:
                    sock.send(line)
                    md5.update(line)  # 写入要加密的东西
    
            data = sock.recv(8096)
            md5_val = md5.hexdigest()  # 获取密文
            sock.send(md5_val.encode("utf8"))
            is_valid = sock.recv(8096).decode("utf8")
            if is_valid == "203":
                print("传递成功,文件完整!")
    
            else:
                print("文件上传失败!")
    
    
    
    
        elif num == 2:
            filename = input("请输入要下载的文件名:")
            if os.path.isfile("put/"+"%s副本"% filename):  # 如果是存在的文件,返回True.否则返回False)
                row1 = input("文件还未下载完毕,是否续传?(1&2)")
                if row1 == "1":
                    filename_size = os.path.getsize("put/"+"%s副本"% filename)  # 返回path的大小
                else:
                    filename_size = 0
                # ret = struct.pack("i", filename_size)   #打包
                # sock.send(ret)  #发送已下载文件的大小
            else:
                filename_size = 0
    
            file_info = {
                "filename":filename,
                "filename_size":filename_size
            }
            file_info_json = json.dumps(file_info).encode("utf8")  # 将字典序列化
            sock.send(file_info_json)
    
            filesize = sock.recv(8096) #获取文件大小
            filesize = struct.unpack("i", filesize)[0]  # 解包
    
            # 循环接收文件
            with open("put/"+"%s副本"% filename, "ab") as f:
                # recv_data_length = 0
                while filename_size < filesize:
                    data = sock.recv(8096)
                    filename_size += len(data)
                    f.write(data)
                    # MD5摘要
                    md5.update(data)  # 写入要加密的的东西
                    # print("文件总大小:%s,已成功接收%s" % (filesize, recv_data_length))
    
    
            sock.send(b"OK")
            # print(md5.hexdigest())
            md5_val = md5.hexdigest()  # 解密
            client_md5 = sock.recv(8096).decode('utf8')
            if md5_val == client_md5:
                sock.send(b"203")
                print("接收成功!")
                os.rename("put/"+"%s副本"% filename,"put/"+filename)
            else:
                sock.send(b"204")
                print("接收失败!")
    客户端

      

    三丶进度条

      

    import time
    import sys
    
    
    def progress_test():
        bar_length = 10     #   #号的长度
        for percent in range(0, 101):
            hashes = '#' * int(percent / 100.0 * bar_length)
            spaces = ' ' * (bar_length - len(hashes))
            sys.stdout.write("
    Percent: [%s] %d%%" % (hashes + spaces, percent))
            sys.stdout.flush()
            time.sleep(0.05)    #相隔多少秒执行一次
    
    progress_test()
  • 相关阅读:
    [导入]Interesting Finds: 2007.12.17
    [导入]Interesting Finds: 2007.12.15
    [导入]Interesting Finds: 2007.12.13
    Interesting Finds: 2007.12.22
    吾生也有涯,而知也无涯。
    Hello world
    学习了clipboard复制剪切插件的使用
    在博客园学习成长
    命名空间概述
    Linux vi/vim
  • 原文地址:https://www.cnblogs.com/qicun/p/9605581.html
Copyright © 2020-2023  润新知