day 27

一.基于tcp协议的通信套接字(循环链接)

服务端代码:
from socket import *

server = socket(AF_INET, SOCK_STREAM)
server.bind(("127.0.0.1", 8081))
server.listen(5)
# 链接循环
while True:
    conn, addr = server.accept()
    # 通信循环
    while True:
        try:      #try 与 except 的作用是:当客户端单方面的断开连接是,接收异常,并断开连接,结束此次服务,但服务器的服务不会断开
            data = conn.recv(1024)
            print(data.decode("utf-8"))
            msg = input(">>>:").strip()
            conn.send(msg.encode("utf-8"))
        except ConnectionResetError:
            break
    conn.close()

server.close()



客户端代码:
from socket import  *
client = socket(AF_INET,SOCK_STREAM)
client.connect(("127.0.0.1",8081))
#通信循环
while True:
    data1= input(">>>:").strip()
    if len(data1)==0:continue
    client.send(data1.encode("utf-8"))
    data=client.recv(1024)
    print(data.decode("utf-8"))

client.close()

二.模拟ssh实现远程执行命令(会出现粘包问题)

服务端代码:
from socket import *
import subprocess

server = socket(AF_INET, SOCK_STREAM)
server.bind(("127.0.0.1", 8081))
server.listen(5)
# 连接循环
while True:
    conn, addr = server.accept()
    # 通信循环
    while True:
        try:
            # 接收信息:
            cmd = conn.recv(1024)
            obj = subprocess.Popen(cmd.decode("utf-8"), shell=True,
                                   stderr=subprocess.PIPE,
                                   stdout=subprocess.PIPE
                                   )
            stdout = obj.stdout.read()
            stderr = obj.stderr.read()
            # 发送消息
            conn.send(stderr + stdout)
        except ConnectionResetError:
            break
    conn.close()

server.close()


客户端代码:
from socket import *

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"))
    # 接受信息
    data1=client.recv(1024)
    print(data1.decode("gbk"))
    
client.close()

三.模块struct

import  struct

data=struct.pack("i",12312)
print(data,len(data))   #会将一定长度的整型,变成长度固定的字节

data1=struct.unpack("i",data)
print(data1[0])

#粘包问题:是tcp协议流式传输数据的方式导致的
#解决粘包问题:接收端能够精确的收干净每个数据包,没有残留

四.二.模拟ssh实现远程执行命令(解决现粘包问题的初级方法)

服务端代码:
from socket import  *
import  subprocess
import  struct

server= socket(AF_INET,SOCK_STREAM)
server.bind(("127.0.0.1",8081))
server.listen(5)
#链接循环
while True:
    conn,addr = server.accept()
    #通信循环
    while True:
        try:
            #接收信息
            cmd = conn.recv(1024)
            obj=subprocess.Popen(cmd.decode("utf-8"),
                                 shell=True,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 )
            stdout=obj.stdout.read()
            stderr=obj.stderr.read()
            header= struct.pack("i",len(stdout)+len(stderr))
            #先发送报头长度:(统一为四个字节)
            conn.send(header)
            #再发送真实数据:
            conn.send(stderr+stdout)
        except ConnectionResetError:
            break
    conn.close()

server.close()



客户端代码:
from socket import  *
import  struct

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. 先接收报头的信息
    header=client.recv(4)
    tottal_size=struct.unpack("i",header)[0]   #为真实数据的长度
    # 2. 再接收真正的数据
    cmd_res=b""
    size_cmd=0
    while size_cmd<tottal_size:
        data=client.recv(1024)
        size_cmd += len(data)
        cmd_res += data
    print(cmd_res.decode('gbk'))

client.close()


五.模拟ssh实现远程执行命令(解决现粘包问题的终级方法)

服务端代码:
from socket import  *
import  struct
import json
import subprocess

server=socket(AF_INET,SOCK_STREAM)
server.bind(("127.0.0.1",8081))
server.listen(5)
#链接循环
while True:
    conn,addr=server.accept()
    #通信循环
    while True:
        try:
            cmd = server.recv(1024)
            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":"erhwer",
                "header_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(stderr+stdout)
        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 先收四个bytes 再解出报头长度
    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)
    tottal_size=header_dic["header_size"]
    #接收真实的数据
    cmd_res= b""
    res_size=0
    while res_size < tottal_size:
        data=client.recv(1024)
        cmd_res += data
        res_size += len(data)
    print(cmd_res.decode("gbk"))

client.close()

 

posted @ 2018-09-03 17:18  jiangxiaolong_mrx  阅读(121)  评论(0编辑  收藏  举报