• 网络编程模块的使用


    一、在TCP协议中我们如何解决粘包的问题

      (1)TCP协议为啥会产生粘包问题:(流式协议,补充:数据的可靠性--->必须得到回应才会在内存删除)

         1.接收:我根本不知道接收的总长度。————》落包的现象

         2.发送方:会把数据量小的并且时间间隔较短的数据一次性打包发送。---》粘包

       (2)UDP协议:基于数据报协议

              没有双向通道

        1.UDP不存在粘包问题

        2、客户端可以发空

        3.UDP可以实现并发的效果(qq程序)

        4.即使服务端不存在,也不影响客户端向服务端发数据

      TCP------>打电话

      UDP----->发短信

      

      1.通过struck模块

      

      具体看实例:

    import struck
    import json
    
    第一步:建立字典 
    
    my_dic = {"file_name": "澳门最大赌场线上赌场开业了!",
              "file_size": 435413543654364364546546544445}
    第二:我们进行对字典的序列化
    data_json = json.dumps(my_dic)
    
    得到字符串,我们要对他进行z转换转成计算机能识别的语言:二进制类型
    data_bytes = data_json.encode("utf-8")
    
    print(data_bytes)    #
    
    第三:开始对我们得到的信息打包-->打包成“i” 模式下的字节
    data = struck.pick("i",len( data_bytes))
    
    print(data)    #4
    第四解包:
    res =struck.unpick("i", data)[0]
    prit(res)
    

      

    字符串:{"file_name": "u6fb3u95e8u6700u5927u8d4cu573au7ebfu4e0au8d4cu573au5f00u4e1au4e86uff01", "file_size": 435413543654364364546546544445}
    
    二进制:b'{"file_name": "\u6fb3\u95e8\u6700\u5927\u8d4c\u573a\u7ebf\u4e0a\u8d4c\u573a\u5f00\u4e1a\u4e86\uff01", "file_size": 435413543654364364546546544445}'
    
    “i”格式的4个字节数:b'x92x00x00x00'
    
    4
    
    146
    

     2.subprocess模块的运用:作用--->可以解决客户端与服务端循环交流

      

    服务端:
    import socket # 套接字模块 import subprocess # 三流 import json # 序列化 import struct # 解决粘包问题 """ 服务端必备三要素: 1.要有固定的ip和port 2.要能24小时进行服务 3.能承受高并发 并发:看上去像同时进行 """

      

    # 第一步:
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))  # 绑定通信地址
    server.listen(5)  # 半链接池
    
    # 第二步 开始通信循环
    while True:
        conn, addr = server.accept()  # d等待服务
        while True:
            try:
                cmd = conn.recv(1024).decode('utf-8')  # 接收到的是二进制要进行解码
    
                if len(cmd) == 0: break # 若接收到的信息为0时 直接退出
                obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                stdout = obj.stdout.read()
                stderr = obj.stderr.read()
                #   1.制作一个固定长度的报头
                header = struct.pack('i', len(stdout + stderr))
                #   2.发送固定长度的报头
                conn.send(header)
                #   3.发送真实数据的长度
                # conn.send(stdout )
                # conn.send(stderr )
                #   由于tcp协议的特点上面和下面完全是等价的
                conn.send(stderr + stdout)
            except ConnectionResetError:  # 捕获异常
                break  # 直接退出
        conn.close()  # 关闭连接
    

      

     

    客户端:
    import socket
    import struct
    # 第一步
    client = socket.socket()
    client.connect(('127.0.0.1', 8080))
    # 第二步
    while True:
        cmd = input('>>>:').encode('utf-8')
        if len(cmd) == 0: continue
        client.send(cmd)
        # 解析报头获取的真实数据的长度
        header = client.recv(4)
        total_size = struct.unpack('i', header)[0]
    
        # 循环接收信息
        recv_size = 0
        data = b''
        while recv_size < total_size :
            res = client.recv(1024)
            data += res
            recv_size +=len(res)
        print(data.decode('gbk'))
    

      3.tcp大文件上传示范列:

      

    客户端:
    import  socket
    import struck
    import json 
    
    第一步建立连接:
    socket.socket()
    
    client.connect(('127.0.0.1', 8080))
    
    第二步:
    文件大小:file_size=os.path.getsize(r'文件路径=path=os.path.jion()')
    设置文件名;file_name="性感美女在线发牌.mp4'
    
    第三:设置一个字典
    my_dic={"fiel_name":file_name,"file_size':file_size}
    
    #序列化字典--》转成二进制模式
    data_bytes=json.dumps(my_dic).encode("utf-8)
    
    #制作报头:
    header= struck.pack('i', len(data_bytes))
    #发送报头
    client.sent(header)
    #发送字典编码后的二进 制3字符串
    client.send(header_bytes)
    b'{"file_name": "\u6027\u611f\u7f8e\u5973\u5728\u7ebf\u53d1\u724c.mp4", 
    "file_size": 254031692, "msg": "\u6ce8\u610f\u8eab\u4f53\u54e6"}' #开始发送真实信息 with open("文件路径“,“rb”)as f: for line in : client.sent(line)

      

      

    服务端:
    import json 
    import os
    import socket
    import struck
    
    第一步:建立连接
    socket.socket()
    server.bind(("127.0.0.1",  8080))
    server.lisent(5)   #半链接池
    
    第二步:开始接收信息
    while True:
        conn, addr = srever.accept()    #等待接收信息
        while True:
             try:
                # 接收报头
                header = server.recv(4)    #接收到报头4个字节
                #j解析报头,获取报头长度
                henader_len = struck.unpack("i'', header)[0]
                #获取字典
                  header_bytes = conn.recv(header_len)
                #heaher_dic = json. loads(header_bytes.decode(utf-8))
                #开始循环接收文件传到到本地
                #file_name = header_dic.get("file_name')
                 #file-size = header_dic.get(file_name')
                   recv_size =0 
                    with open(file_name,"wd")as f:
        
                                   while recv_size < file_size:
                                   data = conn.recv(1024)
                                   f.write(data)
                                   recv_size = recv_size+len(data)
                                   print(recv_size) #第一次接收的值
                                   break
                   print(header_dic.get("msg"))    # 字典点.get是他的内置方法
              except ConnectionResetError:
                   break
          conn.close()                
    

      4.qq简易版:

      

    QQ版udp:客户端
    import socket
    
    第一步:建立连接
    
    server = socket.socket(stype = socket.SOCK_DGRAM)
    server.bind(('127.0.0.1',8080))
    
    while True:
        add, addr=server.recvfrom(1024)
        print(msg,decode('utf-8'))
        data = inpout(">>>:").encode('utf_8')
        server.sendto(data.addr)
    

      

    qq版udp服务端:
    
    
    import socket
    
    client = socket.socket(type= socket.SOCK_DGRAM)
    server_addr = ('127.0.0.1',8080)
    
    while True:
        msg = input(">>>:")
        msg = '客户端1的消息%s'% msg
        client.sendto(msg.encode('utf-8'),server_addr)
        data,addr= client.recvfrom(1024)
    
        print(data.decode('utf-8'))
    ------------------------------------------
    
    import socket
    
    client = socket,socket(type=socket.SOCK_DGMAM)
    
    server_addr ('127.0.0.1'),8080)
    
    
    while True:
        msg= input(">>>:”)
        msg = "客户端2的消息%s''%msg
        client.sendto(msg.encode('utf_8'), server_addr)
        data ,addr = client.recvfrom(1024)
        
    
        print(data.decode("utf-8'))
    --------------------------------------------
    
    
    import socket
    
    client = socket.socket(type= socket.SOCK_DGRAM)
    server_addr = ('127.0.0.1',8080)
    
    while True:
        msg = input(">>>:")
        msg = '客户端3的消息%s'% msg
        client.sendto(msg.encode('utf-8'),server_addr)
        data,addr= client.recvfrom(1024)
    
        print(data.decode('utf-8'))
    -----------------------------------------------------
    

      

      5.socktedsrever模块

        TCP:通过socketserver进行完成TCP

      

    TCP:服务端:(实现并发)
    import socketserver
    
    class Mybaby(socketserver.BaseRequestHandler):
        def handle(self):
            # 循环同心
            while True:
                #
                data = self.request.recv(1024)  # 收信息
                print(data)
                self.request.send(data.upper())
    
    
    if __name__ == '__main__':
        server = socketserver.ThreadingTCPServer(('127.0.01', 8080), Mybaby)
        server.serve_forever()
    

      

    TCP:客户端
    import socket
    
    
    client = socket.socket()
    client.connect(('127.0.0.1',8080))
    
    while True:
        client.send(b'hello')
        data = client.recv(1024)
        print(data)
    

        2.UDP:通过soc

    import socketserver
    import import 
    
    socket.socket()
    
    
    calss Myud(socketserver.BaseRequestHandler):
        def handler(self):
        #j建立通信循环
            while True:
                data,sock=self.request #受消息 self.request相当于你的conn通信对象
                print(data)
                sock.sendto(data.upper(),self.client_addr) #self.client_addr相当于客户地址
    if __name__ = "__name__" :
           server = socketserver.ThreadingUDPSserver(('127.0.0.1'),8080)
           server.server_forever()
    

      

    客户端:
    import socket
    
    socket.socket(socket.SOCK_DGRAM)
    
    server_addr =('127.0.0.1',8080)
    
    while True:
         client.sendto(b'hello',server_addr)
        data ,addr = client.recvfrom(1024)
        print(data, addr)
        time.sleep(1)
    

      

    socketserver实现并发

        

        1.能够实现并发效果

                并发:看起来像同时运行就能称为并发

        2.UDP在使用的时后,多个客户端要有一些IO操作不然容易卡死

      6.并发编程

        操作系统的发展史:

        1.多道技术:

            空间上的复用(多个程序共用一套硬件设备,他是多道技术实现时间上的复用的基础 )

            时间上的复用(单个CPU的电脑上,起了多个应用程序。cpu快速切换,给人感觉像是同时运行)

        cpu哪两种情况下才会切换:(西庵堡村当前运行的状态)

        1.一个任务占用cpu时间过长或被操作系统强行夺走cpu的权限(比串行效率反而降低)

        2.一个任务遇到IO操作时,也会被系统强行夺走CPU的执行权限(比起串行效率更高)

        补充:

          并发 :看上去像同时进行的

          并行:同时运行

          单核计算永远不可能实现并行。

  • 相关阅读:
    使用duilib链接错误 _declspec(dllimport)
    USB磁盘VID和PID 对应到次盘盘符相关文章
    路径拆分函数
    COM问题
    将对话框嵌入父窗体
    duilib的caption上的Edit无法激活
    LoadLibrary失败,GetLastError MOD_NOT_FOUND
    windows字符串
    windows界面库种类
    windows插件框架
  • 原文地址:https://www.cnblogs.com/mofujin/p/10816817.html
Copyright © 2020-2023  润新知