码迷,mamicode.com
首页 > 其他好文 > 详细

基于tcp协议的套接字通信:远程执行命令

时间:2019-11-02 17:26:58      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:+=   erro   stream   utf-8   std   set   字符串类型   json序列化   内存   

1.struct模块

技术图片
#1、把整型数字转成bytes类型
#2、转成的bytes是固定长度的

import struct
import json

header_dic = {
    total_size: 31222222222121,
    md5: 123svsaef123sdfasdf,
    filename: a.txt
}

#序列化:内存中的数据结构----》转成一种中间格式(字符串)----》存到文件中
header_json=json.dumps(header_dic)
print(header_json,type(header_json))

#编码:编码后的结果为bytes类型
header_bytes=header_json.encode(utf-8)
header_size=len(header_bytes)
print(header_size)  # 81

#打包
obj=struct.pack(i,header_size)
print(obj,len(obj))  # b‘Q\x00\x00\x00‘ 4

#解包
obj2=struct.unpack(i,obj)
print(obj2)  # (81,)
View Code

打印结果:

技术图片
{"total_size": 31222222222121, "md5": "123svsaef123sdfasdf", "filename": "a.txt"} <class str>
81
bQ\x00\x00\x00 4
(81,)
result

2.通讯整个流程:

‘‘‘
流程:
    服务端:制作报头,把报头信息丢到报头字典里,字典序列化得到json字符串,encode得到bytes
          ---->发报头长度(struct.pack打成4个bytes)--->发送报头---->发真实数据
          
    客户端:先接收4个bytes:struct.unpack解包报头长度--->接收报头-->
             解析报头:decode得到字符串,反序列化得到报头--->根据报头内的信息,收取真实的数据

‘‘‘

3.具体代码如下:

服务端:

from socket import *
import subprocess
import struct
import json

server=socket(AF_INET,SOCK_STREAM)
server.bind((127.0.0.1,8080))
server.listen(5)               #监听客户端的链接请求

while True:
    conn,client_addr=server.accept() #(连接对象,客户端的ip和端口)  conn:tcp三次握手的一个产物,可以用来收发消息
    print(client_addr)     #此处client_addr的作用是可以知道哪个客户端建的链接,和通讯无关
    while True:
        try:
            cmd=conn.recv(1024)   #cmd为bytes类型,
            obj=subprocess.Popen(cmd.decode(utf-8),   
                                 shell=True,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE
                                 )
            stdout=obj.stdout.read()  #系统命令,解码需要gbk
            stderr=obj.stderr.read()

            # 1、制作报头
            header_dic={
                total_size:len(stdout) + len(stderr),
                md5:123svsaef123sdfasdf,
                filename:a.txt
            }
            header_json = json.dumps(header_dic)         #json序列化报头
            header_bytes = header_json.encode(utf-8)   #字符串类型---->bytes类型,发送

            # 2、先发送报头的长度
            header_size=len(header_bytes)
            conn.send(struct.pack(i,header_size))

            # 3、发送报头
            conn.send(header_bytes)

            # 4、发送真实的数据
            conn.send(stdout)     #send只能发bytes类型
            conn.send(stderr)
        except ConnectionResetError:
            break
    conn.close()
server.close()

客户端:

from socket import *
import struct
import json           

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

while True:
    cmd=input(>>>: ).strip()
    if not cmd:continue
    client.send(cmd.encode(utf-8))     #把命令结果发给服务器
    #1、先收报头的长度根据报头内的信息,收取真实的数据
    header_size=struct.unpack(i,client.recv(4))[0]    #bytes类型,想拿到报头长度要对bytes进行解出

    #2、接收报头
    header_bytes=client.recv(header_size)   #对应服务端的发送报头

    #3、解析报头
    header_json=header_bytes.decode(utf-8)    #bytes类型---->字符串类型
    header_dic=json.loads(header_json)         #反序列化拿到报头
    print(header_dic)

    total_size=header_dic[ total_size]
    # print(total_size) #1025
    #4、接收数据

    recv_size=0
    res=b‘‘
    while recv_size < total_size:
        recv_data=client.recv(1024)
        res+=recv_data
        recv_size+=len(recv_data)

    print(res.decode(gbk))
client.close()

 

基于tcp协议的套接字通信:远程执行命令

标签:+=   erro   stream   utf-8   std   set   字符串类型   json序列化   内存   

原文地址:https://www.cnblogs.com/zh-xiaoyuan/p/11783058.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!