我有一个WSASocket,当连接时调用CreateProcess和服务器cmd.exe,我想在进程hStdInput和Socket Handle之间实现一个管道,以解析通过套接字发送的命令,除因为当我运行“ ping 127.0.0.1”之类的命令并必须等待输出时,在我通过套接字发送更多数据之前,什么都没有显示,似乎我的ReadFile调用阻止了hStdOut处理程序发送任何内容。有没有什么办法解决这一问题?请不要被我编写我的代码的冒犯,我将这个项目编写为学习练习,请提供任何帮助。
int syncShell(SOCKET *ConnectSocket) {
int iResult = 0;
printf("Spawning process\n");
char Process[] = "C:\\Windows\\System32\\cmd.exe";
STARTUPINFO sinfo;
PROCESS_INFORMATION pinfo;
memset(&sinfo, 0, sizeof(sinfo));
sinfo.cb = sizeof(sinfo);
sinfo.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
// create pipe for external commands
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
HANDLE hReadPipe = NULL, hWritePipe = NULL;
iResult = CreatePipe(&hReadPipe, &hWritePipe, &saAttr, DEFAULT_BUFLEN);
if (iResult == 0) {
printf("Pipe Error");
}
sinfo.hStdOutput = sinfo.hStdError = (HANDLE) *ConnectSocket;
sinfo.hStdInput = hReadPipe;
if (!CreateProcessA(NULL, Process, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo, &pinfo)) {
printf("CreateProcess failed (%d).\n", GetLastError());
}
// implement pipe logic
char buf[DEFAULT_BUFLEN];
DWORD len = 0;
WSABUF DataBuf;
while (1) {
// causing the block?
iResult = ReadFile((HANDLE) *ConnectSocket, buf, DEFAULT_BUFLEN, &len, NULL);
if (iResult == 0) {
printf("File Error or non-blocking");
}
else {
printf("%d: %.*s\n", len, len, buf);
WriteFile(hWritePipe, buf, len, NULL, NULL);
}
Sleep(1000);
}
WaitForSingleObject(pinfo.hProcess, INFINITE); // waits till proc finishes
CloseHandle(pinfo.hProcess);
CloseHandle(pinfo.hThread);
printf("Process exited\n");
return 0;
}
答案 0 :(得分:1)
首先,根据[ReadFile
]文档:
对于异步读取操作,hFile可以是 由
FILE_FLAG_OVERLAPPED
函数以CreateFile
标志打开, 或socket
或accept
函数返回的套接字句柄。
socket
默认情况下使用WSA_FLAG_OVERLAPPED
创建套接字句柄。
如果传递重叠的句柄并将ERROR_INVALID_PARAMETER
的最后一个参数设置为ReadFile
,则会得到错误代码87(NULL
)。
使用重叠的示例:
OVERLAPPED oRead = { 0 };
oRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
iResult = ReadFile((HANDLE)ConnectSocket, buf, DEFAULT_BUFLEN, &len, &oRead);
if (!iResult && GetLastError() == ERROR_IO_PENDING)
{
WaitForSingleObject(oRead.hEvent, INFINITE);
}
buf[oRead.InternalHigh] = 0; //set string terminator for printf
printf("%s\n", buf);
WriteFile(hWritePipe1, buf, oRead.InternalHigh, NULL, NULL);
最好直接使用recv()
:
iResult = recv(ConnectSocket, buf, DEFAULT_BUFLEN, 0);
buf[iResult] = 0; //set string terminator for printf
printf("%s\n", buf);
WriteFile(hWritePipe1, buf, iResult, NULL, NULL);
此外,重叠的套接字可用于将IO重定向到子进程 您可以创建2个管道来与子进程进行通信:
iResult = CreatePipe(&hReadPipe1, &hWritePipe1, &saAttr, DEFAULT_BUFLEN);
if (iResult == 0) {
printf("Pipe Error");
}
iResult = CreatePipe(&hReadPipe2, &hWritePipe2, &saAttr, DEFAULT_BUFLEN);
if (iResult == 0) {
printf("Pipe Error");
}
从子进程(cmd.exe
)中读取,然后发送给客户端。
或者,