• python套接字编程实现ntp服务和远程命令执行


    python套接字编程实现ntp服务和远程命令执行

      目录

    基于udp实现ntp服务
    基于tcp实现远程命令执行
    基于udp实现远程命令执行
    tcp与udp的比较
    

      

    前面关于套接字基础请查阅

    https://www.cnblogs.com/-wenli/p/10173888.html

    基于udp实现ntp服务

    服务端

    import time
    from socket import *
    
    
    def main():
        ip_port = ('127.0.0.1', 4444)
        buffer_size = 1024
    
        s1 = socket(AF_INET,SOCK_DGRAM) #数据报
        s1.bind(ip_port)
    
        while True:
            data,addr=  s1.recvfrom(buffer_size)
            if not data:
                fmt = '%Y-%m-%d %X' #udp服务可以接收空信息,如果为空信息,则为默认格式
            else:
                fmt = '%'+data.decode('utf-8') #自定义格式
    
            back_time=time.strftime(fmt)
            s1.sendto(back_time.encode('utf-8'),addr)
    
    
    
    if __name__ =='__main__':
        main()
    

    客户端

    from socket import *
    
    
    def main():
        ip_port = ('127.0.0.1', 4444)
        buffer_size = 1024
    
        s2 = socket(AF_INET,SOCK_DGRAM) #数据报
        print('请输入回车获取当前完整时间,Y获取当前年份,m获取当前月份,,d获取当前日期,X获取当前时间')
        while True:
            data = input('-->:')
            s2.sendto(data.encode('utf--8'),ip_port) #udp发信息没有链接,所以每一个发送信息都需要指定ip和端口
    
            data1,addr=s2.recvfrom(buffer_size)
    
            print('标准时间:',data1.decode('utf-8'))
    
    
    
    
    
    if __name__ =='__main__':
        main()
    

      

    运行结果


    基于tcp实现远程执行命令

    服务端

    from socket import  *
    import subprocess
    
    
    def main():
        ip_port=('127.0.0.1',8080)
        back_log=5
        buffer_size=1024
    
    
        s1 = socket(AF_INET,SOCK_STREAM)
        s1.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        s1.bind(ip_port)
        s1.listen(back_log)
    
        while True:
            conn,addr=s1.accept()
    
            while True:
                try:
                    #收信息
                     cmd = conn.recv(buffer_size)
                     if not cmd:break
                     print('收到的命令是:',cmd.decode('utf-8'))
    
    
                     #执行命令
                     res = subprocess.Popen(cmd.decode('utf-8'),shell=True,
                                            stderr=subprocess.PIPE,
                                            stdout=subprocess.PIPE,
                                            stdin=subprocess.PIPE)
    
                     err = res.stderr.read()
                     if  err:
                         cmd_res=err
                     else:
                         cmd_res=res.stdout.read()
    
                    #发信息
                    #注意:执行的结果默认jbk编码方式,所以客户端必须使用gbk方式解码
                     conn.send(cmd_res)
    
                except Exception:
                    break
            conn.close()
        s1.close()  # 关闭服务端套接字
    
    
    if __name__ == '__main__':
        main()
    

      

    客户端

    from socket import  *
    
    
    def main():
        ip_port=('127.0.0.1',8080)
        buffer_size=2048
    
    
        s1 = socket(AF_INET,SOCK_STREAM)
        s1.connect(ip_port)
    
        while True:
            cmd = input('-->')
            if not cmd:continue
            if cmd =='quite':break
            s1.send(cmd.encode('utf-8'))
    
            reponse = s1.recv(buffer_size)
            print('命令执行结果:',reponse.decode('gbk'))
    
        s1.close()
    
    if __name__=='__main__':
        main()
    

      

     补充知识

    补充: 你从管道中读取输出,只能读取一次,输出到屏幕,管道里面的数据就会取出来
    res=subprocess.Popen('dir',shell=True,stdout=subprocess.PIPE) 第一个参数为命令,第二个参数为shell=Ture,意思是使用shell作为命令解释器去解释前面的命令,后面是重定向标准输入和标准输出以及错误输出
    (默认输出到屏幕) res.stdout.read()  从管道读取结果
    res.stderr.read() 从管道读取错误
    res.stdin.read() 从管道读取输入 这个程序解决两个问题: 客户端正常断开连接,在服务端加上if not cmd:break,判断接收信息为空就结束接收信息的循环,继续等待下一次连接,正常情况,服务端不会接收到空。 客户毒案异常中断,在服务端上加上异常处理

    运行结果

     

    基于udp实现远程执行命令

    服务端

    from socket import *
    
    import subprocess
    
    
    
    def main():
        ip_port = ('127.0.0.1', 9003)
    
        bufsize = 1024
    
        udp_server = socket(AF_INET, SOCK_DGRAM)
    
        udp_server.bind(ip_port)
    
        while True:
            try:
                # 收消息
    
                cmd, addr = udp_server.recvfrom(bufsize)
    
                print('用户命令----->', cmd.decode('utf-8'))
    
            # 逻辑处理
    
                res = subprocess.Popen(cmd.decode('utf-8'), shell=True,
                                       stderr=subprocess.PIPE,
                                       stdout=subprocess.PIPE,
                                       stdin=subprocess.PIPE)
    
                err = res.stderr.read()
                if err:
                    cmd_res = err
                else:
                    cmd_res = res.stdout.read()
                if not cmd_res:
                    cmd_res = '执行成功'.encode('gbk')
                
                # 发信息
                # 注意:执行的结果默认jbk编码方式,所以客户端必须使用gbk方式解码
                udp_server.sendto(cmd_res,addr)
            except Exception:
                break
    
    if __name__=='__main__':
        main()
    

      

    客户端

    from socket import *
    
    
    
    def main():
        ip_port=('127.0.0.1',9003)
    
        buffer_size=1024
        udp_client=socket(AF_INET,SOCK_DGRAM)
    
        while True:
            cmd = input('-->')
            if not cmd: continue
            if cmd == 'quite': break
            udp_client.sendto(cmd.encode('utf-8'),ip_port)
            reponse,addr = udp_client.recvfrom(buffer_size)
            print('命令执行结果:', reponse.decode('gbk'))
        udp_client.close()
    
    if __name__=='__main__':
        main()
    

      

    运行结果

     

    tcp与udp的比较

    tcp基于链接通信
    
    基于链接,则需要listen(backlog),指定连接池的大小
    基于链接,必须先运行的服务端,然后客户端发起链接请求
    对于mac系统:如果一端断开了链接,那另外一端的链接也跟着完蛋recv将不会阻塞,收到的是空(解决方法是:服务端在收消息后加上if判断,空消息就break掉通信循环)
    对于windows/linux系统:如果一端断开了链接,那另外一端的链接也跟着完蛋recv将不会阻塞,收到的是空(解决方法是:服务端通信循环内加异常处理,捕捉到异常后就break掉通讯循环)
    udp无链接
    
    无链接,因而无需listen(backlog),更加没有什么连接池之说了
    无链接,udp的sendinto不用管是否有一个正在运行的服务端,可以己端一个劲的发消息,只不过数据丢失
    recvfrom收的数据小于sendinto发送的数据时,在mac和linux系统上数据直接丢失,在windows系统上发送的比接收的大直接报错
    只有sendinto发送数据没有recvfrom收数据,数据丢失
    

      

  • 相关阅读:
    java实现第三届蓝桥杯数量周期
    java实现第三届蓝桥杯数量周期
    java实现第三届蓝桥杯数量周期
    java实现第三届蓝桥杯排日程
    java实现第三届蓝桥杯排日程
    java实现第三届蓝桥杯排日程
    java实现第三届蓝桥杯排日程
    java实现第三届蓝桥杯排日程
    使用UE配置Python编程环境
    常用的UltraEdit使用技巧
  • 原文地址:https://www.cnblogs.com/-wenli/p/10175939.html
Copyright © 2020-2023  润新知