网络通信之:服务端远程执行客户端命令

服务端:

import socket,subprocess

sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sk.bind(('localhost',8080))
sk.listen(5)

while True:
    conn,client_addr = sk.accept()
    print(conn)
    print('客户端的ip和端口:',client_addr)

    while True:
        try:
            data = conn.recv(8096)
            print('客户端ip:%s,消息:%s '%(client_addr[0],data.decode('utf-8')))
            if len(data) == 0:break
            res = subprocess.Popen(data.decode('utf-8'),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE
                                   )
            msg = res.stdout.read()
            if len(msg)==0:
                msg=  res.stderr.read()
            conn.send(msg)
        except Exception:
            break
    conn.close()
sk.close()

客户端:

import socket

sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sk.connect(('127.0.0.1',8080))

while True:
    msg = input('>>>>>>>:').strip()
    if len(msg) == 0:continue
    sk.send(msg.encode('utf-8'))
    data = sk.recv(8096)
    print('服务端发来消息:',data.decode('gbk'))

sk.close()

 

 

以上代码可以实现务端远程执行客户端命令,但是会出现粘包问题,下面来解决粘包问题:

 

方案一

服务端:

import struct
import socket,subprocess

server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

server.bind(('127.0.0.1',8080))

server.listen(5)

while True:
    conn,client_addr = server.accept()
    print(conn)
    print('客户端的ip和端口是:',client_addr)

    while True:
        try:
            data = conn.recv(1024)
            if len(data)==0:break
            print('客户端的ip是:%s,客户端的消息是:%s' %(client_addr[0],data.decode('utf-8')))
            res = subprocess.Popen(data.decode('utf-8'),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE
                                   )

            stdout_res = res.stdout.read()
            stderr_res = res.stdout.read()
            total_size = len(stdout_res)+len(stderr_res)
            print(total_size)
            # 1.先发头信息(固定长度的Bytes):对数据的描述
            # int->固定长度的Bytes
            # conn.send(str(total_size).encode('utf-8'))  #原来的方案
            header = struct.pack('i',total_size)
            conn.send(header)
            # 2.再发真实数据
            conn.send(stdout_res)
            conn.send(stderr_res)
        except Exception:
            break
    conn.close()
server.close()

 

客户端:

import socket
import struct


client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('127.0.0.1',8080))

while True:
    msg = input('>>>>>>>:').strip()
    if len(msg) == 0:continue
    client.send(msg.encode('utf-8'))

    # 解决粘包问题思路:
    # 一.先收固定长度的头:解析出数据的描述信息,包括数据的总大小total_size
    header = client.recv(4)
    total_size = struct.unpack('i',header)[0]
    # 二、根据解析出的描述信息,接收真实的数据
    # 2.recv_size=0,循环接收,每接受一次,recv_size += 接收的长度
    # 3.直到recv_size = total_size,结束循环

    recv_size = 0
    while recv_size < total_size:
        recv_data = client.recv(1024)
        recv_size += len(recv_data)
        print(recv_data.decode('gbk'),end='')
    else:
        print()

    # data = client.recv(8096)
    # print('服务端发来的消息:',data.decode('gbk'))



client.close()

 

 

终极版-解决粘包问题

服务端:

import socket
import subprocess
import struct
import json

server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
    conn,client_addr = server.accept()
    print(conn)
    print('客户端的ip和端口是:',client_addr)
    while True:
        try:
            data = conn.recv(1024)
            if len(data) ==0:
                break
            print('客户端的ip是:%s,客户端发来的消息是:%s' %(client_addr[0],data.decode('utf-8')))

            res = subprocess.Popen(data.decode('utf-8'),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE
                                   )
            stdout_res = res.stdout.read()
            stderr_res = res.stderr.read()
            total_size = len(stdout_res) + len(stderr_res)
            print('服务端执行后的消息长度为:',total_size)
            # 一、制作头
            header_dic = {
                'filename':'a.txt',
                'total_size':total_size,
                'md5':'fadfadsfdf'
            }
            json_str = json.dumps(header_dic)
            json_str_bytes = json_str.encode('utf-8')

            # 1.先把头的长度发过去
            x = struct.pack('i',len(json_str_bytes))
            conn.send(x)
            # 2.发头信息
            conn.send(json_str_bytes)
            # 2.再发真实信息
            conn.send(stdout_res)
            conn.send(stderr_res)
        except Exception:
            break

    conn.close()

server.close()

客户端:


import socket
import struct
import json

client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('127.0.0.1',8080))

while True:
msg = input('>>>>>>>:').strip()
if len(msg) == 0:continue

client.send(msg.encode('utf-8'))
# 接收端
# 1.先接收4个字节,从中提取出头部长度
x = client.recv(4)
header_len = struct.unpack('i',x)[0]

# 2.接收头,并解析
json_str_bytes = client.recv(header_len)
json_str = json_str_bytes.decode('utf-8')
header_dic = json.loads(json_str)
print(header_dic)
total_size = header_dic['total_size']
recv_size = 0
while recv_size < total_size:
recv_data = client.recv(1024)
recv_size += len(recv_data)
print(recv_data.decode('gbk'),end='')
else:
print()
client.close()


posted @ 2021-08-06 16:12  五仁味儿月饼  阅读(143)  评论(0)    收藏  举报