python模块——socket (实现简单的C/S架构端通信操作CMD)
# 服务端代码
#!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = "loki" import socket import subprocess server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ip_port = ('127.0.0.1', 8011) server.bind(ip_port) server.listen(5) # 链接循环 while 1: print('Waiting...') conn, addr = server.accept() print('-->conn: ', conn) print('-->addr: ', addr) print('Got it...') while 1: try: cmd = conn.recv(1024) res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) conn.send(res.stdout.read()) conn.send(res.stderr.read()) except Exception: break conn.close() # server.close()
客户端
#!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = "loki" import socket client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ip_port = ('127.0.0.1', 8011) client.connect(ip_port) # 通信循环 while 1: # 发消息 cmd = input('>>: ').strip() if not cmd: continue client.send(bytes(cmd, encoding='utf-8')) # 收消息 data = client.recv(8196) print(data.decode('gbk')) # client.close()
以上代码是基于TCP 流的方式进行C/S控制,注意编码Linux适用于utf-8,Windows适用于gbk
已知BUG:
1.在接受的信息大于8196(或者你自己定义的值的时候)可能会出现粘包问题
2.执行可执行程序或者需要交互的cmd命令,client会宕住,需要重新开客户端
3.如果是作为纯py脚本使用还需要进行sys.platform的系统判断,如果是win采用编码gbk,linux采用编码utf-8
4.以上代码仅供学习参考使用
# 解决粘包问题的TCP版本 —— server
#!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = "loki" import socket import subprocess import struct user_input = input('Please input server_ip: ').strip() ip_port = ('%s' % user_input, 9991) buff_size = 1024 stick_pack_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) stick_pack_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) stick_pack_server.bind(ip_port) stick_pack_server.listen(5) while 1: print('Waiting...') msg, address = stick_pack_server.accept() print("msg-->: ", msg) print("addr-->: ", address) while 1: try: cmd = msg.recv(buff_size) if not msg: break res = subprocess.Popen(cmd.decode("utf-8"), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) stderr = res.stderr.read() stdout = res.stdout.read() data_size = len(stderr) + len(stdout) # send header msg.send(struct.pack("i", data_size)) # send real data msg.send(stderr) msg.send(stdout) except Exception as e: print('---->', e) break msg.close() # phone.close()
# 解决粘包问题的TCP版本 —— client
#!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = "loki" import socket import struct user_input = input("Please input client_ip: ").strip() ip_port = ('%s' % user_input, 9991) buff_size = 1024 stick_pack_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) stick_pack_client.connect(ip_port) while 1: # send message cmd = input('>>: ').strip() if not cmd: continue stick_pack_client.send(cmd.encode("utf-8")) # receive header baotou = stick_pack_client.recv(4) data_size = struct.unpack("i", baotou)[0] # receive data receive_size = 0 receive_data = b'' while receive_size < data_size: data = stick_pack_client.recv(1024) receive_size += len(data) receive_data += data print(receive_data.decode("gbk")) # stick_pack_client.close()
Wrap-up
1.注意tcp客户端需要使用 xx.connect()
2.注意tcp服务端发送消息是使用的accept,以及发送消息使用的是conn
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库