• Socket传输简单的信息以及粘包问题的解决


      一、简单的socket程序——传输简短文字:

    # -*- coding: utf-8  -*-
    # -*- Author: WangHW -*-
    import socket
    
    whw_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    whw_client.connect(('127.0.0.1',9001))
    while 1:
        cmd = input('>>>:').strip()
        if not cmd:
            continue
        whw_client.send(cmd.encode('utf-8'))
        recv_data = whw_client.recv(1024)
        data = recv_data.decode('utf-8')
        print('server data:',data)
    client
    # -*- coding: utf-8  -*-
    # -*- Author: WangHW -*-
    import socket
    
    whw_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    whw_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    whw_server.bind(('127.0.0.1',9001))
    whw_server.listen(5)
    print('listening......')
    conn,addr = whw_server.accept()
    #通信循环
    while 1:
        try:
            recv_data = conn.recv(1024)
            data = recv_data.decode('utf-8')
            print('client data:',data)
            conn.send(data.swapcase().encode('utf-8'))
        except ConnectionResetError:
            break
    conn.close()
    server

      演示如下:

    二、模拟SSH命令——解决粘包问题版:

      关于粘包问题的解决方案:

      在服务器端,由于解析出来的命令结果非常多,所以我们在发送结果之前需要先给客户端发送一个“报文”,这个报文保存着具体的命令结果的信息——其中关键的信息就是结果的长度,客户端只有知道这个结果的长度后,才能制定相应的接收规则:

    # -*- coding: utf-8  -*-
    # -*- Author: WangHW -*-
    import socket
    import json
    import struct
    
    whw_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    whw_client.connect(('127.0.0.1',9000))
    while 1:
        try:
            cmd = input('>>>:').strip()
            if not cmd:
                continue
            #发命令
            whw_client.send(cmd.encode('utf-8'))
            #1.收报头长度
            obj = whw_client.recv(10)
            #注意structunpack出来的[0]值为长度信息
            header_size = struct.unpack('i',obj)[0]
            #2.收报头——根据报头长度来收
            header_bytes = whw_client.recv(header_size)
            #3.从报头中解析出'total_size'
            header_json = header_bytes.decode('utf-8')
            header_dic = json.loads(header_json)
            total_size = header_dic['total_size']
            #根据total_size开始接收真实的数据
            recv_size = 0
            recv_data = b''
            while recv_size < total_size:
                res = whw_client.recv(1024)
                recv_data += res
                recv_size += len(res)
            print('命令结果:
    ',recv_data.decode('gbk'))
        except Exception as e:
            whw_client.close()
    client
    # -*- coding: utf-8  -*-
    # -*- Author: WangHW -*-
    import socket
    import subprocess
    import json
    import struct
    
    whw_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    whw_server.bind(('127.0.0.1',9000))
    whw_server.listen(5)
    print('Listening......')
    conn,addr = whw_server.accept()
    while 1:
        try:
            #收命令
            cmd_recv = conn.recv(1024).decode('utf-8')
            #解析命令
            obj = subprocess.Popen(cmd_recv,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
            stdout = obj.stdout.read()
            stderr = obj.stderr.read()
            #将命令返回给客户端
            #1.制作固定报头——注意报头里面要包含数据的总长度!
            header_dic = {'filename':'whw','total_size':len(stdout)+len(stderr)}
            header_json = json.dumps(header_dic)
            header_bytes = header_json.encode('utf-8')
            #2.发送报头长度——struct:把数字打成固定长度
            conn.send(struct.pack('i',len(header_bytes)))
            #3.发送报头
            conn.send(header_bytes)
            #4.发送真实数据
            conn.send(stdout)
            conn.send(stderr)
        except ConnectionResetError:
            break
    
    conn.close()
    server

      演示如下:

     

  • 相关阅读:
    Java中==和equals的区别
    (转)JAVA-反射机制的使用
    JAVA三框架工作原理是什么?
    Spring的IoC模式
    JavaEE中为什么出现中文乱码?
    Android--Apache HttpClient(2种实现)
    Android之网络----使用HttpClient发送HTTP请求(通过get方法获取数据)
    Android—Http连接之GET/POST请求
    2014 12 04
    struts2的HelloWorld的基本过程
  • 原文地址:https://www.cnblogs.com/paulwhw/p/9092629.html
Copyright © 2020-2023  润新知