• python-study-30


    1、远程执行命令的c/s架构的软件 (模拟ssh远程执行命令)
    from socket import *
    import subprocess
    import struct
    import json
    
    server=socket(AF_INET,SOCK_STREAM)  #创建一个服务器的套接字
    
    server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #解决方案
    # 重启服务端时可能会遇到地址占用
    # 这个是由于你的服务端仍然存在四次挥手的time_wait状态在占用地址
    
    server.bind(('127.0.0.1',8080))   #把地址绑定到套接字
    
    server.listen(5)  #监听链接
    
    while True:  #链接循环,这个链接结束,继续处理下一个客户端链接,不会因为一个客户端链接结束,导致服务器结束
        conn,client_addr=server.accept()
        print('新的客户端',client_addr)
    
        while True: #收发循环,实现循环通讯
            try:  #windows突然断开,服务端会因为没有链接 而崩溃
                cmd=conn.recv(1024) #cmd=b'dir'   接收的是bytes类型 使用时要解码
                if len(cmd) == 0:break #linux如果突然断开,自己给自己收空,就死循环
    
                # 运行系统命令
                obj=subprocess.Popen(cmd.decode('utf-8'), #接收的是bytes类型 使用时要解码
                                 shell=True,
                                 stderr=subprocess.PIPE,
                                 stdout=subprocess.PIPE
                                 )
    
                stdout=obj.stdout.read() #从管道接收正确输出,bytes类型
                stderr=obj.stderr.read() #从管道接收错误输出,bytes类型
    
                #先制作报头是字典但因为通讯是bytes类型所以要转换  dic--str--bytes
                header_dic={
                    'filename':'a.txt',
                    'total_size':len(stdout) + len(stderr),
                    'hash':'xasf123213123'
                }
                header_json=json.dumps(header_dic) #先用json序列化,变成str类型
                header_bytes=header_json.encode('utf-8') #str编码成bytes类型
    
                #1、先把报头的长度len(header_bytes)打包成4个bytes,然后发送
                conn.send(struct.pack('i',len(header_bytes)))  #int -->bytes
                #2、发送报头
                conn.send(header_bytes)  #报头传过去
                #3、再发送真实的数据
                conn.send(stdout)
                conn.send(stderr)
            except ConnectionResetError:
                break
    
        conn.close()
    server.close()
    解决粘包问题终极版本/server
    from socket import *
    import struct
    import json
    
    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8080))
    
    while True: #收发循环,解决循环通讯的问题
        cmd=input('>>: ').strip()
    
        if len(cmd) == 0:continue  #如果发空的话,系统接收为0不会发给服务端,服务端不会响应,客户端还在等着接收,所以就会卡在这里
        client.send(cmd.encode('utf-8')) #str==》bytes 发给服务端
    
        #1、先收4个字节,该4个字节中包含报头的长度
        header_len=struct.unpack('i',client.recv(4))[0] #4个字节反解成int类型数字,代表报头的长度
    
        #2、再接收报头
        header_bytes=client.recv(header_len) #在接收报头长度的字节
    
        #从报头中解析出想要的内容
        header_json=header_bytes.decode('utf-8') #字节解码成json字符串
        header_dic=json.loads(header_json) #json字符串在反序列化得到字典
        print(header_dic)
        total_size=header_dic['total_size']   #从报头得到真实数据的字节长度
    
        #3、再收真实的数据 循环接收字节
        recv_size=0
        res=b''
        while recv_size < total_size :
            data=client.recv(1024)
            res+=data
            recv_size+=len(data)
    
        print(res.decode('gbk'))  #因为命令是系统执行的返回给python的 所以要遵循系统的编码标准 也就是gbk
    client.close()
    解决粘包问题终极版本/client

    2、粘包问题
    操作系统在发包时,遵循tcp协议,
    tcp协议使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包发送。
    这样,接收端,就难于分辨出来了。
    发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)
    
    
    粘包问题主要还是因为接收方不知道消息之间的界限
    
    
    ps:
    发送和接收都是以操作系统基础
    View Code
  • 相关阅读:
    USACOZero Sum
    USACOControlling Companies
    USACOParty Lamps
    USACOMoney Systems
    UVa11292
    USACOLongest Prefix
    USACOThe Tamworth Two
    USACORunaround Numbers
    业内常见电子病历编辑器简单比较(1)编辑控件来源比较
    GB(国标)字典大全
  • 原文地址:https://www.cnblogs.com/xujinjin18/p/9285715.html
Copyright © 2020-2023  润新知