2018-7-22-Python全栈开发day30-socket原理与粘包-part3-基于TCP实现远程命令,并且解决粘包现象

1.知识准备

  subprocess模块

  运行一个命令,将这个命令的结果,放到管道内,然后从管道内取出,

  res=subprocee.Popen('dir',shell=True,stdout=subprocess.PIPE)#将命令输出的结果放到管道内

  res.stdout.read()#读取管道内的数据,且只能读取一次,是b形式的

2.

服务端:

from socket import *
import subprocess

ip_port=('127.0.0.1',8080)
back_log=5
buffer_size=1024

tcp_server=socket(AF_INET,SOCK_STREAM)
tcp_server.bind(ip_port)
tcp_server.listen(back_log)

while 1:#循环监听,
    con,addr=tcp_server.accept()
    print('this is new client ',addr)
    while 1:
        data=con.recv(buffer_size)
        if not data:continue
        res=subprocess.Popen(data.decode('gbk'),shell=True,
                             stdout=subprocess.PIPE,
                             stdin=subprocess.PIPE,
                             stderr=subprocess.PIPE)#拿到的是b形式的
        if not res:
            print('执行成功')
        err_msg=res.stderr.read()#b形式
        if err_msg:
            con.send(err_msg)
        else:
            out_msg=res.stdout.read()
            con.send(out_msg)
远程命令服务端

客户端“

from socket import *
client_server=socket(AF_INET,SOCK_STREAM)
client_server.connect(('127.0.0.1',8080))

while True:
    msg=input('please input cmd')
    if not msg:continue
    client_server.send(msg.encode('gbk'))
    data=client_server.recv(1024)
    print('this is recv',data.decode('gbk'))
远程命令客户端

3.问题:粘包

  3.1粘包的原因:

    对于tcp来说,,粘包有两个原因,

      1.数据较小,间隔较短,多段数据在一块,另一端在接收的时候只收到一条#tcp中send和recv是不对应的

      2.数据较大,一次性并不能从内核态缓存中全部拿出来,下一次再拿的时候先拿上一次遗留的

  3.2 粘包的解决思路

     在每次send之前,将需要发的数据长度告知接收方,然后接收方改变buffer_size,来确定一次性可以取完。

  3.3 程序实现

 服务端:

# from socket import *
# import subprocess
# ip_port=('127.0.0.1',8080)
# back_log=5
# buffer_size=1024
#
# tcp_server=socket(AF_INET,SOCK_STREAM)
# tcp_server.bind(ip_port)
# tcp_server.listen(back_log)
#
# while 1:#循环监听,
#     con,addr=tcp_server.accept()
#     print('this is new client ',addr)
#     while 1:
#         data=con.recv(buffer_size)
#         if not data:continue
#         res=subprocess.Popen(data.decode('gbk'),shell=True,
#                              stdout=subprocess.PIPE,
#                              stdin=subprocess.PIPE,
#                              stderr=subprocess.PIPE)#拿到的是b形式的
#         if not res:
#             print('执行成功')
#         err_msg=res.stderr.read()#b形式
#         if err_msg:
#             con.send(err_msg)
#         else:
#             out_msg=res.stdout.read()
#             con.send(out_msg)








#解决粘包
from socket import *
import subprocess
ip_port=('127.0.0.1',8080)
back_log=5
buffer_size=1024

tcp_server=socket(AF_INET,SOCK_STREAM)
tcp_server.bind(ip_port)
tcp_server.listen(back_log)

while 1:#循环监听,
    con,addr=tcp_server.accept()
    print('this is new client ',addr)
    while 1:
        data=con.recv(buffer_size)
        if not data:continue
        res=subprocess.Popen(data.decode('gbk'),shell=True,
                             stdout=subprocess.PIPE,
                             stdin=subprocess.PIPE,
                             stderr=subprocess.PIPE)#拿到的是b形式的
        if not res:
            print('执行成功')
        err_msg=res.stderr.read()#b形式
        if err_msg:
            res1=err_msg
        else:
            res1=res.stdout.read()
        #以上实现原理相同,对数据进行处理
        #
        length=len(res1)
        con.send(str(length).encode('gbk'))
        data2=con.recv(1024)
        if data2.decode('utf-8') == 'ready':

            con.send(res1)
解决粘包-服务端

客户端:

# from socket import *
# client_server=socket(AF_INET,SOCK_STREAM)
# client_server.connect(('127.0.0.1',8080))
#
# while True:
#     msg=input('please input cmd')
#     if not msg:continue
#     client_server.send(msg.encode('gbk'))
#     data=client_server.recv(1024)
#     print('this is recv',data.decode('gbk'))
#





from socket import *
client_server=socket(AF_INET,SOCK_STREAM)
client_server.connect(('127.0.0.1',8080))
buffer_size=1024
while True:
    msg=input('please input cmd')
    if not msg:continue
    client_server.send(msg.encode('gbk'))
    data_length=client_server.recv(buffer_size)#就是收到的数据长度
    data_length1=int(data_length.decode('gbk'))#进行解码并转换为整形
    if data_length1 <= buffer_size:
        client_server.send('ready'.encode('gbk'))
    else:
        buffer_size=data_length1
        client_server.send('ready'.encode('gbk'))
    data2 = client_server.recv(buffer_size)
    print('this is recv',data2.decode('gbk'))
客户端

 

posted @ 2018-07-22 22:38  brownbearye  阅读(165)  评论(0)    收藏  举报