TCP Proxy mit C++
-
Hallo,
Ich wollte mir einen C++ "Proxy" machen, allerdings weiß ich nicht wie ich anfangen soll. Ich habe 2 Verbindungen, die gleichzeitig abgefragt werden müssen. theoretisch kann ich 2 threads öffnen, wobei der eine an dem einen socket mit recv wartet und wenn etwas gesendet wird muss es an die andere verbindung gesendet werden, dafür bräuchte der thread aber 2 sockets allerdings kann man nur eine variable übergeben.
wie soll ich das also machen? gibt es vielleicht beispiele oder bereits fertige codes? habe nix gefunden.
Bedanke mich für jede hilfe
-
Welche Mittel/APIs setzt du ein?
Boost? WinAPI? Qt? Was ganz anderes?Naja, wie auch immer, wieso kannst du nur eine Variable übergeben?
Selbst wenn dass nur so wäre,
die Struktur der "mehreren" Variablen ist ja immer gleich, oder?
Dann "bau" dir doch ne Klasse, deren Instanzvariable zu übergibst.
Achtung,volatile
könnte dein Freund sein
Ansonsten sollte es schon so gehen:
-> listener Thread wartet
-> connection kommt rein
-> proxy thread startet
-> leitet request weiter (proxy funktion)
-> nimmt Antwort entgegen
-> proxy thread close
-> listener thread gibt Daten zurückKannst du mal ein bisschen Sample Code posten,
der skizziert, was du bisher hast?//EDIT
Sehe grad deine Signatur.
Benutzt du wirklich Dev-C++?
Das ist doch tot oder?
auf der Website ist immer noch beta5 aktuelle.
Und das wars imho schon vor 4 Jahren oder so.Hol dir ne neue, aktuelle IDE.
Für Windows soll die VC++ EE Edition ganz gut sein, ist ja kostenlos von MS.Mfg Branleb
-
hallo,
danke erstmal
hier ist mein code, so wie ich mir das ca. vorgestellt habe:int main() { int serverSocket; serverSocket = StartServerListening(11111); if (serverSocket == -1) { cout << "Error!\n"; return 1; } int clientSocket; int serversocket; clientSocket = accept(serverSocket, 0, 0); cout<<" Client connected\n"; serversocket=socket(AF_INET,SOCK_STREAM,0); memset(&addr,0,sizeof(SOCKADDR_IN)); addr.sin_family=AF_INET; addr.sin_port=htons(11111); addr.sin_addr.s_addr=inet_addr("x.x.x.x"); connect(serversocket,(SOCKADDR*)&addr,sizeof(SOCKADDR)); cout<<"connected to server\n"; CreateThread(0, 0, (LPTHREAD_START_ROUTINE)listenatclient, &clientsocket, 0, 0); CreateThread(0, 0, (LPTHREAD_START_ROUTINE)listenatserver, &serversocket, 0, 0); } void listenatclient(LPVOID clientsocket) { char inMessagecli[256]; while(true) { recv(clientSocket, inMessagecli, sizeof(inMessagecli), 0); send(serversocket, inMessagecli, sizeof(inMessagecli), 0); } } void listenatserver(LPVOID serversocket) { char inMessageserv[256]; while(true) { recv(serversocket, inMessageserv, sizeof(inMessageserv), 0); send(clientSocket, inMessageserv, sizeof(inMessageserv), 0); } } int StartServerListening(unsigned short port) { WSAData wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) == SOCKET_ERROR) { cout << "Server: Could Not Start Up Winsock!\n"; return -1; } int mySocket = socket(AF_INET, SOCK_STREAM, 0); if (mySocket == SOCKET_ERROR) { cout << "Server: SocketError\n"; return -1; } struct sockaddr_in server; server.sin_family = AF_INET; server.sin_port = htons(port); server.sin_addr.s_addr = INADDR_ANY; if (bind(mySocket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) { cout << "Server: Cant Bind the Socket\n"; closesocket(mySocket); return -1; } if (listen(mySocket, 5) == SOCKET_ERROR) { cout << "No listening socket open!\n"; closesocket(mySocket); return -1; } return mySocket; }
-
schon gelöst... ich bin auf die simple idee gekommen die sockets/ints in ein array zu packen und das zu übergeben
-
Ich versuche gerade einen Proxy zu erstellen und habe mir deinen Code mal angeschaut
Ich versuche einen Proxy zu erstellen, der mit einem SQLServer kommuniziert und bestimmte Statements blockt bzw modifiziert. Das funktioniert auch schon ganz gut, das einzige Problem ist, das meine Threads mit der Zeit immer mehr werden und ich manchmal den Proxy gar nicht mehr beenden kann (selbst Windows fährt nicht mehr runter).Das Problem ist, das der SQLServer und der Client (SQLServer Management Studio) hin und wieder mal eine Connection aufbauen, ansonsten aber relativ lange über eine Connection miteinander kommunizieren. Deswegen habe ich es so gemacht, das jede Connection wieder eine neue Verbindung zum SQLServer aufbaut:
#include <windows.h> #include <winsock.h> #include <stdio.h> #include <iostream> #include <string> using namespace std; /* * GLOBAL VARS */ SOCKET listener = NULL; SOCKET clientsocket = NULL; SOCKET serversocket = NULL; bool isValid = true; bool ListenOnPort(int portno) { WSADATA w; int error = WSAStartup(SCK_VERSION2, &w); if (error) { return false; } if (w.wVersion != SCK_VERSION2) //Wrong Winsock version? { WSACleanup (); return false; } SOCKADDR_IN addr; // The address structure for a TCP socket addr.sin_family = AF_INET; // Address family addr.sin_port = htons (portno); // Assign port to this socket //Accept a connection from any IP using INADDR_ANY addr.sin_addr.s_addr = htonl (INADDR_ANY); listener = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); // Create socket if (listener == INVALID_SOCKET) { return false; } if (bind(listener, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR) { return false; } //Now we can start listening listen(listener, SOMAXCONN); return true; } void CloseConnection () { //Close the socket if it exists if (listener) closesocket(listener); WSACleanup(); } void listenatclient(LPVOID connection) { connection_s* cs = (connection_s*)connection; char inMessagecli[MSG_SIZE]; int result = 0; while(true) { memset(inMessagecli, 0, MSG_SIZE); int rcount = recv((SOCKET)cs->client, inMessagecli, MSG_SIZE, 0); if (rcount != SOCKET_ERROR) { switch (inMessagecli[0]) { case 0x01: // SQL BATCH { isValid = checkSqlStatement(inMessagecli); break; } default: break; } if (isValid) { send((SOCKET)cs->server, inMessagecli, rcount, 0); } else { send((SOCKET)cs->client, error.getBytes(), error.getBytesSize(), 0); isValid = true; } } Sleep(50); } } void listenatserver(LPVOID connection) { connection_s* cs = (connection_s*)connection; char inMessageserv[MSG_SIZE]; while(true) { memset(inMessageserv, 0, MSG_SIZE); int rcount = recv((SOCKET)cs->server, inMessageserv, MSG_SIZE, 0); if (rcount != SOCKET_ERROR) { send((SOCKET)cs->client, inMessageserv, rcount, 0); } Sleep(50); } } int main(int argc, char* argv[]) { // opening the connection port cout << "opening port " << _PORT << "... "; if (!ListenOnPort(_PORT)) { return 1; } // main server loop while(true) { clientsocket = accept(listener, NULL, NULL); if(clientsocket == SOCKET_ERROR) { cerr << "Error in accept(): continuing..." << WSAGetLastError(); return 1; } // connect to the "real" SQLServer int sqlport = _PORT; char sqlip[] = _IP; SOCKADDR_IN target; target.sin_family = AF_INET; target.sin_port = htons (sqlport); target.sin_addr.s_addr = inet_addr(sqlip); serversocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket if (connect(serversocket,(SOCKADDR*)&target,sizeof(SOCKADDR)) == SOCKET_ERROR) { cerr << "error connecting to the server..." << endl; return 1; } connection_s *cs = new connection_s(); cs->listener = listener; cs->client = clientsocket; cs->server = serversocket; // Thread erstellen CreateThread(0, 0, (LPTHREAD_START_ROUTINE)listenatclient, (LPVOID)cs, 0, 0); CreateThread(0, 0, (LPTHREAD_START_ROUTINE)listenatserver, (LPVOID)cs, 0, 0); } // quit the application CloseConnection(); return 0; }
Problem: Ich muss in listenatclient() und listenatserver() in einer Endlosschleife laufen, sonst bekomme ich nicht alle Daten mit und die Kommunikation bricht schnell zusammen.
Diese Methode funktioniert wie gesagt ganz gut, nur das ich irgendwann 100 Threads offen habe und die schon bestehenden Threads nicht schließen kann (da ich auch gar nicht weiß, welche Threads gebraucht werden und welche nicht).Weiß jemand, wie man das lösen kann?
Hat schon mal jemand einen transparenten Proxy gebastelt, und hat ein paar Tipps?
-
Benutze Overlapped I/O, I/O-Completionports oder boost::asio.
-
select
dürfte es auch tun.