将CMD.exe输入 输出 通过管道发送出去

本文介绍了一个使用匿名管道实现应用程序与cmd命令行界面进行双向交互的例子。通过创建两个匿名管道并将其与cmd进程的标准输入和标准输出关联,实现了从外部接收指令并在cmd中执行的功能,同时能够获取cmd执行结果并返回给外部。此过程涉及Windows API函数如CreatePipe、CreateProcess、ReadFile等。

SECURITY_ATTRIBUTES sa;
sa.nLength=12;
sa.lpSecurityDeor=0;
sa.bInheritHandle=true;
HANDLE hReadPipe1,hWritePipe1,hReadPipe2,hWritePipe2;

ret=CreatePipe(&hReadPipe1,&hWritePipe1,&sa,0);//创建两个匿名管道
ret=CreatePipe(&hReadPipe2,&hWritePipe2,&sa,0);

STARTUPINFO si;
ZeroMemory(&si,sizeof(si));
si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdInput = hReadPipe2;
si.hStdOutput = si.hStdError = hWritePipe1;
char cmdLine[] = "cmd.exe";
PROCESS_INFORMATION ProcessInformation;
ret=CreateProcess(NULL,cmdLine,NULL,NULL,1,0,NULL,NULL,&si,&ProcessInformation);//将匿名管道和cmd.exe的输入输出关联


unsigned long lBytesRead;

while(1) 
{
ret=PeekNamedPipe(hReadPipe1,Buff,1024,&lBytesRead,0,0);//管道是否有数据可读
if(lBytesRead) 
{
ret=ReadFile(hReadPipe1,Buff,lBytesRead,&lBytesRead,0);//读取管道里的数据
if(!ret)
break;
ret=send(clientFD,Buff,lBytesRead,0);//将cmd.exe的输出通过socket发送到客户端
if(ret<=0) 
break;
}
else
{
lBytesRead=recv(clientFD,Buff,1024,0);//将socket数据读出
if(lBytesRead<=0)
break;
ret=WriteFile(hWritePipe2,Buff,lBytesRead,&lBytesRead,0);//将接收到的客户端输入写进管道作为cmd.exe输入
send(clientFD,Buff,lBytesRead,0);
if(!ret) break;
}
}
    

这是我现在的服务端import java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) throws Exception { System.out.println("---------服务器启动成功--------"); //1.基础任务任务一二创建Serversocket对象,同时为服务端注册端口。 ServerSocket ses = new ServerSocket(8888); //..进阶任务多线程 while (true) { //2.使用ServerSocket对象,调用一个accept方法,等待客户端连接请求 Socket csoc = ses.accept(); //3.把这个客户端的csoc通信管道,通过有参构造器交给下面独立的线程负责处理,把里面的东西读出来进行通信 new SeverReaderThread(csoc).start(); } } }下面这是我现在的客户端import java.io.DataOutputStream; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; public class Client{ public static void main(String[] args)throws Exception { //基础任务一,使用tcp通信,创建Socket对象,并同时请求与服务端程序的连接 Socket csoc=new Socket("192.168.243.133",8888); //建立双向通信通道 // 2.socket通信管道中得到一个字节输出流,用来发数据给服务端程序。 OutputStream outc =csoc.getOutputStream(); //3、把低级的字节输出流包装成数据输出流 DataOutputStream doutc = new DataOutputStream(outc); Scanner sc = new Scanner(System.in); while (true) { System.out.println("欢迎来到华南农大校科联自科部,请输入你一共要添加几个项目"); String msg = sc.nextLine(); //一旦用户输入了exit,就退出客户端程序 if ("exit".equals(msg)) { System.out.println("欢迎您下次光临!退出成功!"); doutc.close(); csoc.close(); break; } //4、开始写数据出去了,并且及时清理以免占用内存。 doutc.writeUTF(msg); doutc.flush(); System.out.println("已连接----"); } } }下面是我现在的线程import java.io.DataInputStream; import java.io.InputStream; import java.net.Socket; import java.util.ArrayList; import java.util.HashMap; import java.util.Scanner; public class SeverReaderThread extends Thread{ //下面是有参构造器,在这里再创建一个csoc接收处理 private Socket csoc; // 使用 HashMap 存储任务 private static HashMap<Integer, String> tasks = new HashMap<>(); private static int nextId = 1; private static int maxTasks; private static ArrayList<String> invalidInputs = new ArrayList<>(); //使用数组存储任务,定义为static,静态代码块:初始化最大任务数 static { Scanner sc = new Scanner(System.in); maxTasks = sc.nextInt(); // 吃掉换行符 sc.nextLine(); System.out.println("确定好了一共 " + maxTasks + " 条任务哦!"); } public SeverReaderThread(Socket csoc){ //把送进来的csoc管道给到上面的socket,把当前客户管道交给了一个独立的线程对象。 this.csoc=csoc; } @Override public void run() { //进阶任务:处理异常,得到输入流,包装成数据输入流 try{ InputStream is=csoc.getInputStream(); DataInputStream dis=new DataInputStream(is); while(true){ String msg=dis.readUTF(); //基础任务和进阶任务,一共八个功能(有一个是defult里面记录用户错误输入的需求) // 客户端发送的消息一次性以空格拆分为最多三部分 // parts[0]=命令, [1]=ID, [2]=内容(可选) String[] parts = msg.split(" ", 3); // 第一部分:命令名 String command = parts[0]; // 第二部分:任务编号 int taskId = Integer.parseInt(parts[1]); // 第三部分:任务内容(可能没有) String content = (parts.length > 2) ? parts[2] : ""; switch (command) { case "add": if (tasks.size() >= maxTasks) { System.out.println("任务列表已满!"); } else { tasks.put(taskId, content); System.out.println("已添加 -> ID:" + taskId + ", 内容:'" + content + "'"); if (taskId >= nextId) { nextId = taskId + 1; } } break; case "list": System.out.println("--- 当前任务列表 ---"); if (tasks.isEmpty()) { System.out.println("暂无任务"); } else { for (int id : tasks.keySet()) { System.out.println(id + ": " + tasks.get(id)); } } break; case "modify": tasks.put(taskId, content); System.out.println("任务" + taskId + "已修改为: '" + content + "'"); break; case "delete": tasks.remove(taskId); System.out.println("任务" + taskId + "已删除"); break; case "clear": tasks.clear(); nextId = 1; System.out.println("所有任务已清空"); break; case "count": int count = tasks.size(); System.out.println("当前共有 " + count + " 个任务(最多可存 " + maxTasks + " 条)"); break; case "help": System.out.println("==== 帮助菜单 ===="); System.out.println("可用命令如下:"); System.out.println(" add 1 买菜 —— 添加ID=1的任务"); System.out.println(" modify 2 新内容 —— 修改ID=2的任务"); System.out.println(" delete 3 —— 删除ID=3的任务"); System.out.println(" list —— 查看全部任务"); System.out.println(" clear —— 清空所有任务"); System.out.println(" count —— 显示任务总数"); System.out.println(" help —— 显示此帮助信息"); break; default: // 把用户输入的原始消息保存到列表中 invalidInputs.add(msg); System.out.println("未知命令: '" + command + "'"+"抱歉" + "我目前只有这么多功能."); // 打印当前已记录多少条无效输入 System.out.println("但是我当前已记录 " + invalidInputs.size() + " 条功能之外的需求" + "我会努力增加的"); } } } catch (Exception e) { throw new RuntimeException(e); } } 现在尽量小的改动我的客户端服务端和线程,使得客户将任务管理命令(现在线程里客户的管理任务)发送到服务器并接收服务器的响应,服务器接受客户端的命令并且执行任务管理操作并将结果返回给用户,传输过程中要将字节打包成数据流,尽量简单初学,详解代码,标明我要改的地方(比如在第几行)给出修改好之后服务端客户端线程的完成代码,简单初学详解,只用java,识别好我把代码全部给出了
最新发布
10-18
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值