Python入门学习 DAY32 (套接字 远程执行命令 粘包问题)

Python入门学习

DAY32

今日内容:  套接字   远程执行命令    粘包问题

1. 基于tcp通信的套接字程序

服务端

from socket import *

# 服务器必须满足至少三点
# 1. 绑定一个固定的ip和port
# 2. 一直对外提供服务,稳定运行
# 3. 能够支持并发

server = socket(AF_INET, SOCK_STREAM)

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

server.listen(5)

conn, client_addr = server.accept()

#通信循环
while True:
    try:
        data = conn.recv(1024)

        conn.send(data.upper())
    except ConnectionResetError:
        break
conn.close()
server.close()

客户端

from socket import *

client = socket(AF_INET, SOCK_STREAM)

client.connect(('127.0.0.1', 8080))

while True:
    str1 = input( '>>>:').strip()
    client.send(str1.encode('utf-8'))
    data = client.recv(1024)
    print(data)

client.close()

2. 远程执行命令程序(用到subprocess模块)

服务端

from socket import *
import subprocess

# 服务器必须满足至少三点
# 1. 绑定一个固定的ip和port
# 2. 一直对外提供服务,稳定运行
# 3. 能够支持并发

server = socket(AF_INET, SOCK_STREAM)

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

server.listen(5)

# 链接循环
while True:
    conn, client_addr = server.accept()

    # 通信循环
    while True:
        # 捕捉异常防止客户端断开链接导致服务器报错
        try:
            data = conn.recv(1024)

            
            obj = subprocess.Popen(data.decode('utf-8'),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE
                                   )
            stdout = obj.stdout.read()
            stderr = obj.stderr.read()

            conn.send(stdout)

        except ConnectionResetError:
            break

    conn.close()
server.close()

客户端

from socket import *

client = socket(AF_INET, SOCK_STREAM)

client.connect(('192.168.13.126', 8080))

# 通信循环
while True:
    str1 = input('>>>:').strip()
    if str1 == 'q':
        break
    if len(str1) == 0: continue
    client.send(str1.encode('utf-8'))
    data = client.recv(1024)
    print(data.decode('gbk'))

client.close()

3.粘包问题的解决方案

服务器

# 服务端必须满足至少三点:
# 1. 绑定一个固定的ip和port
# 2. 一直对外提供服务,稳定运行
# 3. 能够支持并发
from socket import *
import subprocess
import struct
import json

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

# 链接循环
while True:
    conn, client_addr = server.accept()
    print(client_addr)

    # 通信循环
    while True:
        try:
            cmd = conn.recv(1024)  # cmd=b'dir'
            if len(cmd) == 0: break  # 针对linux系统
            obj = subprocess.Popen(cmd.decode('utf-8'),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE
                                   )
            stdout = obj.stdout.read()
            stderr = obj.stderr.read()
            # 1. 先制作报头
            header_dic = {
                'filename': 'a.txt',
                'md5': 'asdfasdf123123x1',
                'total_size': len(stdout) + len(stderr)
            }
            header_json = json.dumps(header_dic)
            header_bytes = header_json.encode('utf-8')

            # 2. 先发送4个bytes(包含报头的长度)
            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.close()

客户端

from socket import *
import struct
import json

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

# 通信循环
while True:
    cmd=input('>>: ').strip()
    if len(cmd) == 0:continue
    client.send(cmd.encode('utf-8'))
    #1. 先收4bytes,解出报头的长度
    header_size=struct.unpack('i',client.recv(4))[0]

    #2. 再接收报头,拿到header_dic
    header_bytes=client.recv(header_size)
    header_json=header_bytes.decode('utf-8')
    header_dic=json.loads(header_json)
    print(header_dic)
    total_size=header_dic['total_size']

    #3. 接收真正的数据
    cmd_res=b''
    recv_size=0
    while recv_size < total_size:
        data=client.recv(1024)
        recv_size+=len(data)
        cmd_res+=data

    print(cmd_res.decode('gbk'))

client.close()

以上为本次学习内容

 

猜你喜欢

转载自blog.csdn.net/sql121407/article/details/82353297