将进程的IOredirect到Windows套接字

我是新的winsock,我试图写一个服务器套接字,接受新的连接,然后它调用一个外部的可执行文件。 我们如何将外部可执行文件的stdin和stdoutredirect到已被接受的客户端套接字。 我GOOGLE了,发现下面的代码,但它不工作。 新进程已成功创build,但客户端无法从新进程接收任何数据。 我正在使用Windows 7和Visual Studio 2008 Express版本。 任何帮助和意见表示赞赏。 非常感谢!

服务器

#include <winsock2.h> #include <ws2tcpip.h> #include <stdio.h> #pragma comment(lib, "Ws2_32.lib") #define DEFAULT_PORT "27015" #define DEFAULT_BUFLEN 512 int _tmain(int argc, _TCHAR* argv[]) { WSADATA wsaData; int iResult; // Initialize Winsock iResult = WSAStartup(MAKEWORD(2,2), &wsaData); struct addrinfo *result = NULL, *ptr = NULL, hints; ZeroMemory(&hints, sizeof (hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; // Resolve the local address and port to be used by the server iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); SOCKET ListenSocket = INVALID_SOCKET; ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); // Setup the TCP listening socket iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen); freeaddrinfo(result); if ( listen( ListenSocket, SOMAXCONN ) == SOCKET_ERROR ) { printf( "Listen failed with error: %ld\n", WSAGetLastError() ); closesocket(ListenSocket); WSACleanup(); return 1; } SOCKET ClientSocket; ClientSocket = INVALID_SOCKET; // Accept a client socket ClientSocket = accept(ListenSocket, NULL, NULL); if (ClientSocket == INVALID_SOCKET) { printf("accept failed: %d\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } STARTUPINFO si; memset( &si, 0, sizeof( si ) ); si.cb = sizeof( si ); si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; si.hStdInput = (HANDLE)ClientSocket; si.hStdOutput = (HANDLE)ClientSocket; si.hStdError = (HANDLE)ClientSocket; PROCESS_INFORMATION pi; TCHAR cmd[] = TEXT("C:\\Users\\dell\\Desktop\\hello.exe"); if (CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { printf("create process successfully\n"); DWORD i = WaitForSingleObject( pi.hProcess, INFINITE ); printf("%8x\n", i); } CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); closesocket( ClientSocket ); WSACleanup(); } 

客户端

 #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h> #include <stdlib.h> #include <stdio.h> // Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib #pragma comment (lib, "Ws2_32.lib") #pragma comment (lib, "Mswsock.lib") #pragma comment (lib, "AdvApi32.lib") #define DEFAULT_BUFLEN 512 #define DEFAULT_PORT "27015" int _tmain(int argc, _TCHAR* argv[]) { WSADATA wsaData; SOCKET ConnectSocket = INVALID_SOCKET; struct addrinfo *result = NULL, *ptr = NULL, hints; char recvbuf[DEFAULT_BUFLEN]; int iResult; int recvbuflen = DEFAULT_BUFLEN; // Initialize Winsock iResult = WSAStartup(MAKEWORD(2,2), &wsaData); ZeroMemory( &hints, sizeof(hints) ); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; // Resolve the server address and port iResult = getaddrinfo("localhost", DEFAULT_PORT, &hints, &result); // Attempt to connect to an address until one succeeds for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) { // Create a SOCKET for connecting to server ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { printf("socket failed with error: %ld\n", WSAGetLastError()); WSACleanup(); return 1; } // Connect to server. iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); if (iResult == SOCKET_ERROR) { closesocket(ConnectSocket); ConnectSocket = INVALID_SOCKET; continue; } break; } freeaddrinfo(result); if (ConnectSocket == INVALID_SOCKET) { printf("Unable to connect to server!\n"); WSACleanup(); return 1; } // Receive until the peer closes the connection do { iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); if ( iResult > 0 ) printf("Bytes received: %d\n", iResult); else if ( iResult == 0 ) printf("Connection closed\n"); else printf("recv failed with error: %d\n", WSAGetLastError()); } while( iResult > 0 ); // cleanup closesocket(ConnectSocket); WSACleanup(); return 0; } 

外部程序hello.cpp

 int _tmain(int argc, _TCHAR* argv[]) { printf("hello world!\n"); return 0; } 

Solutions Collecting From Web of "将进程的IOredirect到Windows套接字"

Windows将几乎所有东西视为一个HANDLE 。 不是内核对象的套接字是一个例外,它们不能用于重定向。 您需要使用管道,如果您需要将数据发送到套接字或从套接字发送数据,则需要辅助进程来在管道和套接字之间复制数据。

看看win32版本的netcat源代码(如果你能找到它的话),它几乎完全是socket < – > stdin和stdout转发。

其实,你可以将IO重定向到套接字。 只要确保使用WSASocket而不是socket()打开套接字,并且不指定WSA_FLAG_OVERLAPPED。

这个原因有一点涉及。 您提供给CreateProcess进行I / O重定向的任何“标准句柄”都必须不重叠(即不支持重叠的I / O)。 Windows上的套接字在使用套接字()创建时打开,如果使用WSASocket创建,则不重叠。

还要确保在StartupInfo中将bInheritHandles设置为TRUE

套接字不能直接用于重定向。 启动外部进程时,使用CreatePipe()为进程的重定向STDIN / OUT / ERR句柄创建匿名管道,然后使用send()recv()方法使用ReadFile()WriteFile() (或equivilents)通过管道代理套接字和进程之间的数据。 换句话说,当数据到达套接字时,从套接字读取数据并将其写入STDIN管道。 当进程输出数据时,从STDOUT / ERR管道读取数据并将其写入套接字。

说套接字句柄不能用于重定向IO到子进程是不正确的。 我们一直在我们的Web服务器代码中使用CGI。 我们不使用已命名或未命名的管道或中间进程。

a_mole是正确的。 你只需要不重叠的套接字。

您可以使用WSASocket,或者如果您已经使用套接字创建了套接字(或者无法在目标操作系统上使用WSASocket,例如Pre Windows 7 SP1),则可以使用setsockopt将当前线程的SO_OPENTYPE设置为SO_SYNCHRONOUS_NONALERT