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

一丶网络基础补充

  端口:

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

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

       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()
原文地址:https://www.cnblogs.com/qicun/p/9605581.html