netcat mit c++ bedienen
-
Geht das denn nicht sowieso zu, wenn das C++-Programm beendet wird, das diese Konsole gestartet hat?
-
Jedenfalls weiß ich jetzt, wie man STRG-C senden könnte:
mc.doCommand(string(1, 0x03));
oder, einfacher:
mc.doCommand("\x03");Nee, das muss ich wohl noch mal revidieren. Da kommt zwar das ASCII-Zeichen 3 an, aber es hat nicht dieselbe Wirkung wie STRG-C ... mhm.
So, jetzt aber:
Wenn das myConsole - Objekt zerstört wird, schließt es implizit das Write-Ende der Pipe zur Konsole; das veranlasst die Konsole, sich zu schließen. Das Senden von 'exit' ist also obsolet, da das die einzige Aktion im Destruktor ist, ist der ganze Destruktor von myConsole überflüssig.
-
[quote="Belli"]Geht das denn nicht sowieso zu, wenn das C++-Programm beendet wird, das diese Konsole gestartet hat?[/quote]
nein, glücklicherweise nicht^^ das extra fenster bleibt offen und das hauptfenster kann geschlossen werden.
es ist also genauso wie ichs brauche, nachdem ich den exit senden befehl herausgenommen habe. der exit befehl hat nie zum schließen der konsole geführt, da sie das als string interpretiert und per netcat weitergesendet hat
-
Ja, wie erwähnt, kannst Du eigentlich den ganzen Destruktor rausschmeißen. Aber interessant ist es schon. Ich habe mal zum Testen ein kleines Programm in der gestarteten Konsole gestartet, welches nur auf eine Eingabe auf dem Standard-Eingabestrom wartet. Das jedoch terminiert, wenn ich im Hauptprogramm das myConsole-Objekt zerstöre, und die gestartete Konsole schließt sich dann auch. Das netcat muss irgendeine Besonderheit haben, die verhindert, dass das passiert. Aber Du kannst dem netcat dann keine Befehle mehr geben, das ist doch richtig, oder?
-
hm netcat scheint wirklich da irgendwelche lebenserhaltenen maßnahmen zu ergreifen. also netcat lauscht die ganze zeit, deswegen kann man da auch keine befehle mehr senden, ich guck mal was passiert, wenn man mit strg + c das lauschen abbricht, ob man dann befehle senden kann
-
aha, wenn ich diesen lauschmodus mit strg+c abbreche und das hauptfenster geshclossen ist, schließt sich auch das nc fenster.
-
Ja, das ist schon klar, der Standardeingabestrom ist ja umgelenkt und kann nur noch von dem Hauptprogramm aus gefüttert werden. D.h., sobald das myConsole-Objekt zerstört ist, kannst Du keine Eingaben mehr liefern. Und wenn Du mit STRG-C netcat beendest, stellt die Konsole bei ihrer Rückkehr fest, dass sie keinen funktionierenden Eingabestrom mehr hat, und ich denke, dass sie sich deshalb dann schließt.
Die Ströme gehen seltsame Wege ... lol.
-
also ein problem ist noch:
Es werden ja per netcat alle angekommenden daten in die .txt datei geschrieben.
Die möchte ich nun auswerten, aber solange das hauptfenster offen ist erscheint kein text dadrin. erst wenn man das hauptfenster schließt wird die .txt quasi aktualisiert und der ganze empfangen text wird angezeigt.
kann man das irgendwie anders machen, dass der text sofort verfügbar ist?
-
Keine Ahnung ...
im Moment ist mir Dein Szenario nicht klar:
Du startest das C++-Programm, dieses wiederum startet eine Konsole, in der netstat ausgeführt wird. Außerdem öffnest Du manuell noch eine Konsole, in der Du manuell netstat ausführst?
Welches der beteiligten Programme schreibt nun eine txt-Datei, und wie macht es das?
-
Also hast es schon recht gut beschrieben.
ich startet dsa c++ programm, welches mit myconsole eine konsole öffnet wo netcat gestartet wird. netcat lauscht dann an einem port und schreibt alles was an den port gesendet wird in eine text datei. Im endeffekt wird ein GPS tracker positionsdaten an den port senden. ich simuliere jetzt das den tracker in dem ich ein weiteres cmd fenster öffne und mit netcat fake gps daten an den port sende.mit dem c++ programm will ich nun die .txt datei in die die gps daten geschrieben werden auslesen. also die koordinaten in variablen packen um sie weiter verarbeiten zu können.
jetzt ist das problem, dass die gps daten erst in die txt datei kommen, wenn ich das fenster vom c++ programm schließe oder mit return(0); beende. also wenn ich die txt datei öffen, wenn das c++ fenster noch offen ist, bleibt die txt datei leer, erst wenn ich das fenster schließe, wird die datei vllt "refreshed" und die daten sind lesbar.
das ist ein problem^^ ist es so ungefähr klar?
-
Okay, das Problem habe ich glaube ich verstanden, warum das so ist, weiß ich nicht.
Es könnte aber sein, dass das Schreiben in die Datei nur deshalb beginnt, weil das zugehörige myConsole - Objekt zerstört wird. Wenn es Dich nicht stört, dass Du danach keine Kontrolle mehr über das gestartete netcat hast, könntest Du das ja mal versuchen, indem Du das myConsole - Objekt in einem Scope erzeugst, Deine Befehle an netcat absetzt, und dann den Scope verlässt und beobachtest, ob jetzt die Datei gefüllt wird.
-
Ich habe gerade einen kleinen Test gemacht:
Folgendes Testprogramm#include <windows.h> #include <iostream> using namespace std; int main() { while(++i < 1000000) { cout << "chrrrrrr ...\n"; Sleep(300); } }
via
mc.doCommand("test > test.txt");
gestartet und dann einfach mal abgewartet. Es ist nicht so, dass in die test.txt nicht geschrieben wird, es dauert einfach eine Weile, bis das Testprogramm seine Buffer mal flusht. Auch das Startprogramm lief noch, das myConsole - Objekt existierte noch, und nach einer ganzen Weile wurde die test.txt dann doch mal gefüllt. Vermutlich muss erst eine ganze Menge Daten zum Schreiben angefallen sein. Keine Ahnung, ob man das Buffer flushen von außen beeinflussen kann ...
-
hm wielange hat es denn bei dir gedauert? ich hab jetzt schonmal n paar mins gewartet und es ist trotzdem nichts in der txt datei erschienen. erst als ich das haupptfenster wieder geshclossen habe.
wie würde ich denn das myconsole objekt in einem scope erzeugen?
-
jasdefer schrieb:
hm wielange hat es denn bei dir gedauert? ich hab jetzt schonmal n paar mins gewartet und es ist trotzdem nichts in der txt datei erschienen. erst als ich das haupptfenster wieder geshclossen habe.
wie würde ich denn das myconsole objekt in einem scope erzeugen?
Mit meinem og Testprogramm wurde das erste Mal in die txt-Datei geschrieben, als etwa 350 Zeilen erzeugt waren.
Eine Variable in einem Scope erzeugen? Na, entweder in einer Funktion, oder so:
...
{
myConsole mc;
...
}Wenn die Funktion beendet wird, oder im obigen Fall die schließende Klammer erreicht wird, wird mc zerstört und der Destruktor aufgerufen.
Hat bei meinen Experimenten aber nix gebracht ...
-
ich hab auch noch einmal das programm ausgeführt und sehr viel text übertragen lassen. mehr als 350 zeilen. trotzdem wurde die txt datei nicht aktualisiert.
ach das ist mit scope gemeint. das habe ich auch noch einmal probiert, hat aber leider auch nicht funktioniert.
Fällt dir noch eine möglichkeit ein, wie man das Problem lösen könnte? Das würde mir sehr doll helfen
-
ach noch etwas interessantes. Wenn ich das netcat lauschen mit strg+c beende und das hauptfenster schließe wird die textdatei garnichtmehr aktualisiert. also wenn ich mit strg+c die verbindung beende, gehen die informationen die in die txt datei geschrieben werden sollen verloren
-
Ja, ist aber etwas mehr Aufwand. Du könntest zusätzlich zur Umleitung des StandardEingabeStroms auch noch den StandardAusgabeStrom umleiten. Ich habe für so einen Zweck vor kurzem eine Klasse im Konsolen-Forum vorgeschlagen, die habe ich auch als Vorlage für die hier gezeigt genommen.
Allerdings wird die für Deine Zwecke so nicht funktionieren, weil Dein netcat-Programm nicht zu Ende läuft, sondern weiter aktiv bleiben soll.
Du müsstest also ganz grob:
- eine zweite Pipe für die Umleitung des Standard-Ausgabe-Stroms erstellen
- das write-Handle dieser Pipe an den erzeugten Prozess (netcat) vererben
- und in Deinem Programm einen zweiten Thread starten, der sich um das Lesen/Verarbeiten der Ausgabe von netcat kümmert.Sieh Dir also nochmal die Klasse myConsole und die Klasse mySystem aus dem Konsolen-Forum an, versuch die Geschichte mit dem Umleiten der Standard-Eingabeströme zu recherchieren und zu verstehen, und sieh Dir an, wie das mit dem Thread funktioniert.
Wenn Du dann noch Detail-Fragen hast, stell sie ruhig hier. Ein schönes kurzes Beispiel für die Redirektion von STDIN und STDOUT gleichzeitig findest Du z.B. hier:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
Allerdings brauchst Du für Deinen konkreten Fall wie gesagt einen zweiten Thread, obwohl, vielleicht geht es auch so, wenn Du zuerst Deine Befehle an netcat absetzt, und dann beginnst, den Output zu lesen und zu verarbeiten, ja, es hängt halt von den konkreten Anforderungen ab. Sieh Dir das Beispiel aus der MSDN an, vielleicht reicht Dir das schon, wenn Du es ein wenig anpasst.Edit:
Du würdest bei dieser Variante also keine Datei mehr schreiben, sondern die netcat-Ausgaben direkt in Deinem Hauptprogramm lesen.
-
okay, dann werde ich das mal probieren. vielen dank
ich guck mir das alles mal genauer an und versuhch die einzelnen schritte zu vertsehen
-
müsste ich, soweit ich das verstanden hab, dann im endeffekt zwei pipes haben. also pipe.h und pipe2.h zB. eben einmal für die umleitung der eingabgeströme eins und eins für die ausgabeströme?
-
Zwei Pipes ja, aber nicht pipe1.h und pipe2.h ...
Probier mal folgendes(pipe.h und pipe.cpp bleiben wie gehabt):
Das hab ich jetzt nur mal auf die Schnelle so hingerotzt, aber für das Testprogramm funktioniert es:#ifndef MYCONSOLEH #define MYCONSOLEH #include <string> #include "pipe.h" class myConsole { public: myConsole(); void doCommand(std::string command); std::string readFromProcess(); private: pipe writePipe; pipe readPipe; void startCommandProcess(HANDLE wrHandle, HANDLE rdHandle); }; #endif
#include <iostream> #include "myConsole.h" //public myConsole::myConsole() { writePipe.MakeInheritable(pipe::READ); readPipe.MakeInheritable(pipe::WRITE); startCommandProcess(readPipe.GetPipeHandle(pipe::WRITE), writePipe.GetPipeHandle(pipe::READ)); writePipe.ClosePipeHandle(pipe::READ); readPipe.ClosePipeHandle(pipe::WRITE); } void myConsole::doCommand(std::string command) { DWORD ignore; command.append("\n"); WriteFile(writePipe.GetPipeHandle(pipe::WRITE), command.c_str(), command.size(), &ignore, 0); } std::string myConsole::readFromProcess() { char inBuf[256]; DWORD nBytesRead = 0; std::string tmp; ReadFile(readPipe.GetPipeHandle(pipe::READ), inBuf, 256, &nBytesRead, NULL); return std::string(inBuf, nBytesRead); /* while(TRUE) { if (!ReadFile(readPipe.GetPipeHandle(pipe::READ), inBuf, 256, &nBytesRead, NULL) || !nBytesRead) break; for(int i = 0; i < nBytesRead; ++i) { if(inBuf[i] == 10) { result.push_back(tmp); tmp.clear(); } else if(inBuf[i] == 13) ; else tmp.push_back(inBuf[i]); } } */ } //private void myConsole::startCommandProcess(HANDLE wrHandle, HANDLE rdHandle) { PROCESS_INFORMATION pi; STARTUPINFO si; // Set up the start up info struct. ZeroMemory(&si,sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = rdHandle; si.hStdOutput = wrHandle; si.hStdError = wrHandle; // Use this if you want to hide the child: // si.wShowWindow = SW_HIDE; // Note that dwFlags must include STARTF_USESHOWWINDOW if you want to // use the wShowWindow flags. // Launch the process that you want to redirect (in this case, // Child.exe). Make sure Child.exe is in the same directory as // redirect.c launch redirect from a command line to prevent location // confusion. CreateProcess(NULL, "cmd", NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); // Close any unnecessary handles. CloseHandle(pi.hThread); CloseHandle(pi.hProcess); }
Testprogramm:
#include <iostream> #include <string> #include "myConsole.h" using namespace std; int main() { myConsole mc; //einige Kommandos absetzen, bei Dir zB "netcat ..." usw. mc.doCommand("dir"); mc.doCommand("ipconfig"); mc.doCommand("attrib"); //Ab hier die Ausgaben lesen und verarbeiten, hier werden sie einfach //via cout auf die Konsole geschrieben string str; do { str = mc.readFromProcess(); cout << str; }while(str.size()); }
Edit:
Nachteil bei dieser threadlosen Lösung ist, wenn der gestartet Prozess nichts mehr schreibt, bleibt das Programm in readFromProcess hängen.