Redirect IO der Prozess Windows socket
Ich bin neu winsock, versuchte ich zu schreiben, einen server-socket, nimmt neue Verbindung, dann ruft es eine externe ausführbare Datei. Wie können wir die Umleitung von stdin und stdout der externen ausführbaren Datei an den client-socket angenommen. Ich gegoogelt und fand den folgenden code, aber es funktioniert nicht. Der neue Prozess wurde erfolgreich erstellt, aber der Kunde konnte nicht empfangen auch keine Daten aus dem neuen Verfahren. Ich bin mit Windows 7 und Visual Studio 2008 Express edition. Jeder hilft und die Kommentare werden geschätzt. Vielen Dank, sehr viel!
server
#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();
}
client
#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;
}
externen Programm hello.cpp
int _tmain(int argc, _TCHAR* argv[])
{
printf("hello world!\n");
return 0;
}
Du musst angemeldet sein, um einen Kommentar abzugeben.
Windows behandelt fast alles, was als
HANDLE
. Steckdosen, die nicht-kernel-Objekte, sind eine Ausnahme, und Sie können nicht verwendet werden, die für die Umleitung. Sie müssen verwenden Sie ein Rohr, und wenn Sie benötigen, um das senden von Daten an/von einem socket, brauchen Sie einen Helfer-Prozess zum kopieren von Daten zwischen dem Rohr und sockel.Haben Sie einen Blick auf
netcat
- source-code für die win32-version (wenn Sie es finden können), tut es ziemlich genau-Buchse <-> stdin und stdout weiterleiten.Tatsächlich ist, können Sie umleiten, IO-Steckdosen. So stellen Sie sicher, öffnen Sie den sockel mit WSASocket anstelle von socket(), und geben Sie NICHT die WSA_FLAG_OVERLAPPED.
Der Grund dafür ist ein bisschen beteiligt. Jede "Standard-Griffe, die Sie liefern, zu CreateProcess für I/O-Umleitung muss nicht überlappende (ich.e, nicht unterstützen, overlapped I/O). sockets unter Windows geöffnet werden, überlappt, wenn Sie mit socket() und nicht überlappende wenn erstellt, wie oben mit WSASocket.
Auch sicherstellen, dass Sie bInheritHandles auf TRUE in der StartupInfo -
Sockets können nicht verwendet werden, die direkt für die Umleitung. Beim Start des externen Prozesses, verwenden Sie
CreatePipe()
zu erstellen anonyme pipes für die umgeleiteten Standardeingabe (STDIN/OUT/ERR Griffe aus dem Prozess, dann verwenden SieReadFile()
undWriteFile()
(oder equivilents) mitsend()
undrecv()
manuell proxy die Daten, die zwischen der Buchse und der Prozess, sich über die Rohre. In anderen Worten, wenn die Daten kommt, um die Buchse, die Daten Lesen aus dem socket und schreibt Sie in die STDIN pipe. Wenn der Prozess-outputs Daten, Lesen von STDOUT/ERR Rohre und schreiben Sie es an die Steckdose.Es ist nicht richtig zu sagen, dass socket-handles können nicht verwendet werden, für umgeleitete E /a child-Prozesse. Wir tun es alle, die Zeit für die CGI im web-server-code. Wir verwenden nicht benannte oder Unbenannte pipes oder zwischengeschaltete Prozesse.
a_mole korrekt ist. Sie müssen nur nicht-überlappende sockets.
Können Sie entweder Ipproto_icmp, oder wenn Sie die Buchse schon mit sockel (oder nicht verwenden können, Ipproto_icmp auf Ihre Ziel-OS, z.B. in der Vor-Windows 7 SP1) können Sie setsockopt-Option, um die aktuellen Threads SO_OPENTYPE zu SO_SYNCHRONOUS_NONALERT