• 模拟ssh远程执行命令,粘包问题,基于socketserver实现并发的socket


    06.27自我总结

    1.模拟ssh远程执行命令

    利用套接字编来进行远程执行命令

    服务端

    
    from socket import *
    import subprocess
    
    server = socket(AF_INET, SOCK_STREAM)
    
    server.bind(('127.0.0.1', 8000))
    server.listen(5)
    
    print('start...')
    while True:
        conn, client_addr = server.accept()
    
        while True:
            print('from client:', client_addr)
    
            cmd = conn.recv(1024)
            if len(cmd) == 0: break
            print('cmd:', cmd)
    
            obj = subprocess.Popen(cmd.decode('utf8'),  # 输入的cmd命令
                                   shell=True,  # 通过shell运行
                                   stderr=subprocess.PIPE,  # 把错误输出放入管道,以便打印
                                   stdout=subprocess.PIPE)  # 把正确输出放入管道,以便打印
    
            stdout = obj.stdout.read()  # 打印正确输出
            stderr = obj.stderr.read()  # 打印错误输出
    
            conn.send(stdout)
            conn.send(stderr)
    
        conn.close()
    
    server.close()
    

    客户端

    port socket
    
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    client.connect(('127.0.0.1', 8000))
    
    while True:
        data = input('please enter your data')
        client.send(data.encode('utf8'))
        data = client.recv(1024)
    
        print('from server:', data)
    
    client.close()
    

    输入dir命令,由于服务端发送字节少于1024字节,客户端可以接受。

    输入tasklist命令,由于服务端发送字节多于1024字节,客户端只接受部分数据,并且当你再次输入dir命令的时候,客户端会接收dir命令的结果,但是会打印上一次的剩余未发送完的数据,这就是粘包问题

    2.粘包问题和解决粘包问题

    1.粘包问题

    粘包问题主要出现在用TCP协议传输中才会出现的问题,UDP不会出现,因为TCP传输中他会服务端会一次性把所有东西一并丢入缓存区,而读取的内容大小有时候没法准确的做到一一读取,所有会存在粘包,而UDP他传输的时候是吧一个个内容丢过去,不管客户端能否完全接受到内容他都会接受他制定大小的内容,而内容大于他接受设定的大小时候多余的东西会被丢到

    2.解决粘包问题

    我们通过粘包他产生的问题入手如果我们知道他传输的文件大小我们就可以按他大小完美的全部接受他

    我们引入struct模块:https://www.cnblogs.com/pythonywy/p/11097305.html

    服务端

    from socket import *
    import struct
    import subprocess
    
    sever = socket(AF_INET,SOCK_STREAM)  #创建服务器
    
    sever.bind(('127.0.0.1',8000))   #创建地址
    
    sever.listen(5)     #创建连接个数
    
    while True:
        print('start...')
        conn,addr = sever.accept()      #连接
    
    
        while True:
            try:
                cmd = conn.recv(1024)   #就收CMD指令
                print('cmd:',cmd)
    
                obj = subprocess.Popen(cmd.decode('utf8'),
                                       shell = True,
                                       stderr= subprocess.PIPE,
                                       stdout=subprocess.PIPE)
                stdout = obj.stdout.read()
                stderr = obj.stderr.read()
                # stdout = obj.stdout.read()
    
                count_len = len(stdout) + len(stderr)
    
                guiding_bytes = struct.pack('i',count_len)  #压缩他大小
                conn.send(guiding_bytes)
                conn.send(stdout+stderr)
            except ConnectionRefusedError:
                break
    

    客户端

    from socket import *
    import struct
    
    client = socket(AF_INET,SOCK_STREAM)
    
    client.connect(('127.0.0.1',8000))
    
    while True:
        cmd = input('please enter your cmd>>>')
    
        client.send(cmd.encode('utf8')) #传送命令
    
        count_len = client.recv(4)
    
        fixing_bytes = struct.unpack('i',count_len)[0] #解压
    
        msg = client.recv(fixing_bytes)
    
        print(msg.decode('gbk'))
    

    3.基于UDP套接字编程

    • UDP是无链接的,先启动哪一端都不会报错
    • UDP协议是数据报协议,发空的时候也会自带报头,因此客户端输入空,服务端也能收到

    服务端

    import socket
    
    server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 数据报协议-》UDP
    server.bind(('127.0.0.1', 8080))
    
    while True:
        data, client_addr = server.recvfrom(1024)
        print('===>', data, client_addr)
        server.sendto(data.upper(), client_addr)
    
    server.close()
    

    客户端

    import socket
    
    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 数据报协议-》UDP
    
    while True:
        msg = input('>>: ').strip()  # msg=''
        client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080))
        data, server_addr = client.recvfrom(1024)
        print(data)
    
    client.close()
    

    4.基于socketserver实现并发的socket

    基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环

    socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题)

    1.server类

    2.request类

    3.继承关系

    服务端

    import socketserver
    
    class MyHandler(socketserver.BaseRequestHandler):
        def handle(self):
            # 通信循环
            while True:
                # print(self.client_address)
                # print(self.request) #self.request=conn
    
                try:
                    data = self.request.recv(1024)
                    if len(data) == 0: break
                    self.request.send(data.upper())
                except ConnectionResetError:
                    break
    
    
    if __name__ == '__main__':
        s = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyHandler, bind_and_activate=True)
    
        s.serve_forever()  # 代表连接循环
        # 循环建立连接,每建立一个连接就会启动一个线程(服务员)+调用Myhanlder类产生一个对象,调用该对象下的handle方法,专门与刚刚建立好的连接做通信循环
    

    客户端

    import socket
    
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    phone.connect(('127.0.0.1', 8080))  # 指定服务端ip和端口
    
    while True:
        # msg=input('>>: ').strip() #msg=''
        msg = 'client33333'  # msg=''
        if len(msg) == 0: continue
        phone.send(msg.encode('utf-8'))
        data = phone.recv(1024)
        print(data)
    
    phone.close()
    
  • 相关阅读:
    cs_gallery_Search_PostReindex///cs_GetAnonymousUserID///cs_GetSectionSubscriptionType///cs_GetSectionSubscriptionTypes//cs_GetTotalPostCount
    cs_GetUserIDByAppToken///cs_Group_CreateUpdateDelete
    cs_forums_Post
    cs_forums_Moderate_PostSet
    cs_guestbook_GetPosts///cs_guestbook_Post_Create
    cs_Image_CreateUpdateDelete//cs_InkData_Add//cs_InkData_Delete
    cs_forums_Posts_PostSet
    cs_forums_Posts_PostSet_RSSThreadless//cs_forums_Thread_Get
    cs_LinkCategories_Get///cs_LinkCategory_CreateUpdateDelete//cs_LinkCategory_UpdateSortOrder
    cs_Link_CreateUpdateDelete///cs_Link_UpdateSortOrder
  • 原文地址:https://www.cnblogs.com/pythonywy/p/11097927.html
Copyright © 2020-2023  润新知