zoukankan      html  css  js  c++  java
  • 自定义协议解决粘包问题,阿里云部署,udp协议套接字,socketserver模块的使用

    一:粘包问题解决

    1.tcp流式协议

    (1)粘包原因是底层的算法决定的,设计原因就是提升的效率,tcp流式协议会将时间间隔短,数据量小的字节 合到一起再去发送的。

    (2)只有tcp流式协议才会有粘包现象,udp协议压根没有粘包此说

    (3)发收数据是发给操作系统的接口的缓存,再送到对方的操作系统

    (4)不是一个send唯一对应一个recv

    2.模块struct的用法:

    import struct,json
    header_dic={
    'filename':'a.tat',
    'total_size':100,
    'md5':45612
    }
    header_json = json.dumps(header_dic)
    header_bytes = header_json.encode('utf-8')
    header=struct.pack('i',14873) #i是int类型
    print(header) #结果是:'xd9x90x16x00'
    print(len(header))
    total_size=struct.unpack('i',header)[0] #不加[0]结果会是:1478873,

    print(total_size)

    结果是:

    b'x19:x00x00'
    4
    14873

    3.解决粘包的方法

    服务端:
    
    import subprocess
    from socket import *
    import struct,json
    
    #1买手机
    phone=socket(AF_INET,SOCK_STREAM)
    
    #phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR)
    #2绑定银行卡
    phone.bind(('127.0.0.1',8081)) #元组内放自己的ip地址
    #再次启动服务端,告诉端口已经占用,解决办法有:1.换个端口,8080换掉同时客户端也需要换掉 2.在绑定之前加上下面内容:phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR)
    # 防止位置在 #2绑定银行卡 上面
    
    #3开机
    phone.listen(5)  #半连接池,5以内接受访问请求。  5是访问数量,也就是说除了正在访问的这个,最多再有5个
    
    #4建立链接的请求
    while True:       #需要一个循环不停地与客户端交互
        connect,client=phone.accept()
        print(client)
    
    # 5 收/发消息
        while True:
            try:                           #避免客户端突然中断,不会造成服务端崩溃,针对Windows
                date=connect.recv(1024)    #此处的connect 是 connect,client=phone.accept() 处的,1024是最大的接受字节数
                if len(date)==0:           #针对linux系统的
                    break
                cmd=date.decode('utf-8')
                obj=subprocess.Popen(cmd,shell=True,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE)
                res1=obj.stdout.read()
                res2=obj.stderr.read()
    
                head_dic={
                    'filename':'a.txt',
                    'total_size':len(res1)+len(res2),
                    'md5':'12345dvxvvv'
                }
                header_json=json.dumps(head_dic)
                head_bytes=header_json.encode('utf-8')
    
                #先发4个字节
                connect.send(struct.pack('i',len(head_bytes)))   #字节长度是4个
                #再发报头字典
                connect.send(head_bytes)
                #再发真正的数据
                connect.send(res1)
                connect.send(res2)
            except Exception:
                break
        connect.close()
    客户端:
    
    
    import subprocess
    from socket import *
    import struct,json
    
    #1买手机
    phone=socket(AF_INET,SOCK_STREAM)
    
    #phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR)
    #2绑定银行卡
    phone.bind(('127.0.0.1',8081)) #元组内放自己的ip地址
    #再次启动服务端,告诉端口已经占用,解决办法有:1.换个端口,8080换掉同时客户端也需要换掉 2.在绑定之前加上下面内容:phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR)
    # 防止位置在 #2绑定银行卡 上面
    
    #3开机
    phone.listen(5)  #半连接池,5以内接受访问请求。  5是访问数量,也就是说除了正在访问的这个,最多再有5个
    
    #4建立链接的请求
    while True:       #需要一个循环不停地与客户端交互
        connect,client=phone.accept()
        print(client)
    
    # 5 收/发消息
        while True:
            try:                           #避免客户端突然中断,不会造成服务端崩溃,针对Windows
                date=connect.recv(1024)    #此处的connect 是 connect,client=phone.accept() 处的,1024是最大的接受字节数
                if len(date)==0:           #针对linux系统的
                    break
                cmd=date.decode('utf-8')
                obj=subprocess.Popen(cmd,shell=True,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE)
                res1=obj.stdout.read()
                res2=obj.stderr.read()
    
                head_dic={
                    'filename':'a.txt',
                    'total_size':len(res1)+len(res2),
                    'md5':'12345dvxvvv'
                }
                header_json=json.dumps(head_dic)
                head_bytes=header_json.encode('utf-8')
    
                #先发4个字节
                connect.send(struct.pack('i',len(head_bytes)))   #字节长度是4个
                #再发报头字典
                connect.send(head_bytes)
                #再发真正的数据
                connect.send(res1)
                connect.send(res2)
            except Exception:
                break
        connect.close()

    二:阿里云部署

    1.部署步骤

    (1)

    1.登陆阿里云官网

    https://cn.aliyun.com/
    2.右上角注册,可以用支付宝扫码登陆
    3.点左上角最新活动
    4.然后往下拉有个精彩活动,,里面有个阿里云试用中心,点立即查看
    5.然后选那个右上角有个人用户字样,可以试用一个月的,就可以试用了,但是好像要先实名注册一下

    (2)

    注册完就可以拿到一个公网IP地址,可以试用一个月,还有试用的时候,让你选网速,可以调成最大,就是5Mbps,反正都是免费的,还有最重要的一点,自动续费那个选项千万不要勾选

    申请完还会给你发个短信,短信里会告诉你怎么设置密码,还会有小姐姐给你打电话,发邮箱,让你有问题联系她,密码是一定要设置的,不然上不去,好像还要设置一下端口

    (3)

    全部弄好以后,可以照这个网址https://www.cnblogs.com/kimyeee/p/7250560.html装一下python3,然后就可以当服务端用了

    2.过程中

    三:udp协议的套接字

    特点:没有粘包,只管收发,不稳定,适用于访问和消息发送

    服务端:
    
    
    from socket import *
    server=socket(AF_INET,SOCK_DGRAM)
    server.bind(('127.0.0.1',9999))
    
    while True:
        date,client_addr=server.recvfrom(1024)
        print(date,client_addr)
        server.sendto(date.upper(),client_addr)
    客户端:
    
    
    from socket import *
    client=socket(AF_INET,SOCK_DGRAM)
    
    
    while True:
        msg=input('>>>').strip()
        client.sendto(msg.encode('utf-8'),('127.0.0.1',9999))
        res,sever_adder=client.recvfrom(1024)
        print(res.decode('utf-8'))

    三:socketsever模块的使用

    功能在于同时并发几个客户端

    服务端:
    
    import socketserver
    class MyRequestHandler(socketserver.BaseRequestHandler):
        def handle(self):
            while True:
                try:
                    date=self.request.recv(1024)
                    if len(date)==0:
                        break
                    print(date)
                    self.request.send(date.upper())
                except Exception:
                    break
            self.request.close()
    
    server=socketserver.ThreadingTCPServer(('127.0.0.1',8085),MyRequestHandler,bind_and_activate=True)
    server.serve_forever()
    客户端1:
    
    
    import socket
    #1买手机
    phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)  #流式协议
    
    #2打电话
    phone.connect(('127.0.0.1',8085))
    
    #3发/收数据
    while True:
        msg=input('<<<<').strip()
        if len(msg)==0:                      #避免客户端输入是空的时候出现异常,下面的无法操作
            continue
        phone.send(msg.encode('utf-8'))
        date=phone.recv(1024)
        print(date.decode('utf-8'))
    
    #4关闭
    phone.close()
    客户端2:
    
    
    import socket
    #1买手机
    phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)  #流式协议
    
    #2打电话
    phone.connect(('127.0.0.1',8085))
    
    #3发/收数据
    while True:
        msg=input('<<<<').strip()
        if len(msg)==0:                      #避免客户端输入是空的时候出现异常,下面的无法操作
            continue
        phone.send(msg.encode('utf-8'))
        date=phone.recv(1024)
        print(date.decode('utf-8'))
    
    #4关闭
    phone.close()
  • 相关阅读:
    HDU1255 覆盖的面积 —— 求矩形交面积 线段树 + 扫描线 + 离散化
    HDU1542 Atlantis —— 求矩形面积并 线段树 + 扫描线 + 离散化
    HDU1540 Tunnel Warfare —— 线段树 区间合并
    HDU3974 Assign the task —— dfs时间戳 + 线段树
    HDU4027 Can you answer these queries? —— 线段树 区间修改
    POJ3264 Balanced Lineup —— 线段树单点更新 区间最大最小值
    ZOJ1610 Count the Colors —— 线段树 区间染色
    HDU1698 Just a Hook —— 线段树 区间染色
    POJ2528 Mayor's posters —— 线段树染色 + 离散化
    POJ3468 A Simple Problem with Integers —— 线段树 区间修改
  • 原文地址:https://www.cnblogs.com/dayday-up-a/p/14295216.html
Copyright © 2011-2022 走看看