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

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

  目录

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

  

 

 

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

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

 

 

基于udp实现ntp服务

 

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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()

 

 

 

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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实现远程执行命令

 

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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()

  

 

 

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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()

  

 

 

 

 补充知识

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

 

 

 

 

运行结果

 

 

 

 

基于udp实现远程执行命令

 

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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()

  

 

 

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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的比较

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

  

 

posted @   -零  阅读(1230)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示