UDP-Server im Hintergrund laufen lassen, nur wie?

288 Aufrufe
Gefragt 16, Jun 2017 in Windows 10 von BrosBoss
Hallo, kurz zur Situation: Für ein Projekt sollen Stationsrechner einer Fertigungsanlage über eine SPS (Siemens S7, 1500er Serie) hoch- und runtergefahren werden können. Das Hochfahren war kein Problem, das funktionierte über WOL wie von alleine. Für das Runterfahren habe ich jetzt einen UDP-Server in C geschrieben (mit der Winsock-API), der von der SPS die IP-Adresse des herunterzufahrenden Rechners zugeschickt bekommt, um diesen dann per net use und shutdown herunterzufahren. Dieses Serverprogramm läuft momentan auf einem OPC-Server-PC (Intel NUK), muss jedoch aktiv, also im Vordergrund laufen, um die UDP-Packets zu empfangen. Für diesen Fall funktioniert das Programm auch einwandfrei. Da auf dem NUK aber immer mal wieder gearbeitet werden muss, ist diese Lösung leider nur suboptimal. Wenn das Programm bisher im Hintergrund läuft, wird der Socket erstellt und auch gebunden, aber der recvfrom empfängt einfach nichts. Ich kann mir das anders nicht erklären, als dass Windows das Programm "ignoriert" oder das, was an der Schnittstelle anliegt nicht zum Programm durchreicht, sobald der recvfrom blockiert. Die Idee war jetzt zu versuchen die Priorität des Programms höher zu setzen, sodass es auf jeden Fall die Packets empfängt und die Rechner herunterfährt, auch wenn es im Hintergrund läuft. Unter C# gibts da wohl auch noch ein paar mehr Möglichkeiten hab ich in der Windows-Doku gelesen, aber ich kann nur C und ein bisschen C++, das hilft mir also nicht...

Ich hoffe hier kann mir jemand helfen oder einfach ein paar Denkanstöße geben, am besten mit einigen Hintergrundinfos zur Funktionsweise von Windows. Ich habe den Thread übrigens hier reingestellt, weil auf dem NUK Win10 läuf. Falls es in einem anderen Themenbereich besser passt, einfach verschieben ;)

12 Antworten

0 Punkte
Beantwortet 16, Jun 2017 von BrosBoss
Peinlich... Ich meine natürlich Intel NUC. Naja es ist schon spät... :D
0 Punkte
Beantwortet 17, Jun 2017 von computerschrat Profi (17,897 Punkte)
Hallo BrosBoss,

es könnte sein, dass das Programm, wenn es im Hintergrund gestartet wird, unter einem anderen Benutzer mit anderen Rechten läuft. Damit hat es dann eventuell keinen Zugriff auf die Datenpuffer des Sockets oder kann den Shutdown nicht auslösen.


Gruß
computerschrat
0 Punkte
Beantwortet 17, Jun 2017 von BrosBoss
Hallo computerschrat,

also bisher hatte ich versucht das Programm über die Aufgabenplanung zu starten, da konnte ich einen Benutzer mitsamt PW eingeben und das hab ich auch getan. Als das nicht so recht ging hab ichs später auch mit einem Dienst versucht, den ich mithilfe der srvany.exe erstellt hab. Kann es sein das mir der Zugriff trotzdem irgendwie verweigert wird? Der Benutzer hat natürlich Adminrechte. Aber genau diese Sache mit dem Datenpuffer des Sockets hatte ich als Fehlerquelle im Sinn.

Wenn er den Shutdown nicht auslösen kann, würde folgender Aufruf also nicht aus dem Hintergrund funktionieren:
char command[STR_SIZE] = { 0 };
snprintf(command, sizeof(command), "@SHUTDOWN -s -m \\\\192.168.10.%u -t 10", sh_host);
system(command);
Dass hab ich bisher noch nicht getestet. Mach ich am Montag gleich mal. Was könnte ich stattdessen versuchen? Ich könnte mir eine Batch-Datei schreiben die das gleiche ausführt und von meinem Server gestartet wird, nur ist das doch prinzipiell das gleiche oder?

Gruß
BrosBoss
0 Punkte
Beantwortet 17, Jun 2017 von computerschrat Profi (17,897 Punkte)
Hallo BrosBoss,

eine getestete Lösung habe ich auch nicht. Versuch doch mal, das Programm so zu ändern, dass es kein eigenes Fenster hat. Dann musst du es nicht in den Hintergrund schieben, es stört aber nicht, wenn am Rechner gearbeitet wird.

Gruß
computerschrat
0 Punkte
Beantwortet 17, Jun 2017 von BrosBoss
Hallo computerschrat,

vielleicht hab ich mich dahingehend falsch ausgedrückt, mein Ziel ist gerade dass, was du eben vorgeschlagen hast, also nicht das Konsolenfenster zu minimieren, sondern direkt als Hintergrundtask laufen zu lassen ;)

Wenn das Programm als Dienst oder über die Aufgabenplanung gestartet wird, erzeugt es bei mir kein Fenster. Es funktioniert dann aber auch nicht. Bisher habe ich nur herausgefunden, dass dann der Socket bereits gebunden wurde, weil eine weitere Instanz des Programms mir einen entsprechenden Fehler beim bind() anzeigt. Wie gesagt habe ich die Vermutung, dass Windows mir die Ressourcen für das Programm entzieht, sobald recvfrom() den Socket blockiert. Ich wüsste so auf Anhieb aber auch nicht wie ich diese Vermutung testen könnte. Idee war daher, die Priorität mal auf "hoch" zu setzen und zu schauen. Leider weiß ich aber auch hier nicht ob ich mit dieser Vorgehensweise etwas bewirken könnte und vor allem nicht, ob ich damit in irgendeiner Art und Weise den Server-PC negativ beeinträchtige. Da kenne ich mich zu wenig mit Windows aus. Die Ressourcenvergabe wird ja aber irgendwie über Time-Slicing funktionieren. Wenn also der Task gerade inaktiv ist, und gerade dann ein UDP-Packet ankommt, bekommt mein Programm das natürlich nicht mit. Wenn der Empfangspuffer die Daten dann nicht hält, bis der Task wieder aktiv ist, ist der Shutdown-Request natürlich weg. Ich bräuchte dann eine Art Interrupt, die mein Programm weckt, sobald Daten am Port anliegen.

Ich hoffe meine Denkweise enthält nicht irgendeinen grundlegenden Fehler :)

Gruß
BrosBoss
0 Punkte
Beantwortet 18, Jun 2017 von computerschrat Profi (17,897 Punkte)
Hallo BrosBoss,

ich stochere mal weiter im Nebel herum :-)
Finden sich eventuell in der Ereignisanzeige Meldungen, die auf das Problem hinweisen könnten?

Kannst du über netstat Informationen zum Socket finden?

Könnte es sein, dass deine Hintergrundtask irgendwelche Meldungen loswerden möchte, aber kein Ausgabedevice hat und sich deshalb aufhängt?

Gruß
computerschrat
0 Punkte
Beantwortet 18, Jun 2017 von BrosBoss
Hallo computerschrat,

mit netstat hab ich noch nicht geschaut, werd ich morgen gleich mal machen.

Großartige Meldungen kann ich mir zwar nicht vorstellen, aber ich werds mal prüfen. Letztlich erfolgt die Ausgabe in aller Regel ja über die Konsole, wenn das Programm im Vordergrund läuft. Die interessieren mich auch eigentlich nicht. Aber guter Punkt, wenn es hier nämlich zu Fehlern kommt, müsste ich mir wieder Gedanken zu meinem system()-Aufruf machen, dann würde das aus dem Hintergrund scheinbar nicht klappen.

Danke schon mal soweit, morgen weiß ich hoffentlich mehr.

Gruß
BrosBoss
0 Punkte
Beantwortet 18, Jun 2017 von BrosBoss
achja, und dass Windows so eine Ereignisanzeige hat wusste ich bislang nicht, das schau ich mir dann auch gleich mal an :)
0 Punkte
Beantwortet 19, Jun 2017 von Jaja-ohnepw
Du kannst doch einfach in awl die net use shutdown Geschichte selbst schreiben. Dazu mit wireshark die Pakete mitschreiben und dann mal gucken, welche Bitfolge ausreicht, die Rechner heruntergefahren..
0 Punkte
Beantwortet 19, Jun 2017 von BrosBoss
Hallo Jaja-ohnepw,

die Idee ist mir tatsächlich vor ein paar Wochen auch schon gekommen, nur wollte ich
die Bitfolge in einen DB schreiben. Es gibt in FUP ja bereits fertige Open-User-
Communication-Blöcke, was will ich an dieser Stelle mit AWL... Also gesagt getan, mit
dem WireShark alles aufgezeichnet und siehe da: Es wird über TCP mithilfe eines
SMB-Protokolls (Server Message Block) von Microsoft kommuniziert. Das wiederum
beinhaltet aber eine individuelle Verhandlungsphase, welche Versionen von SMB
überhaupt gesprochen werden. Danach folgt eine verschlüsselte Übertragung eines
Passworts, entweder über NTLM oder über Kerberos. Per NTLM schickt mir der
herunterzufahrende PC einen mechToken, der den Salt-Wert, des
Passworts+Zufallszahl beinhaltet, sowie noch weitere Flags. Ab dann folgen weitere,
auf SMB aufbauende Protokolle für die gemeinsam genutzte Ressource und die IO-
Control. Alles in allem 7 DIN A4-Seiten Hex-Dump. Der Shutdown nicht mitinbegriffen,
der hat so um die 10 DIN A4-Seiten gefüllt. Du siehst, so ohne weiteres ist das mit dem
WireShark nicht möglich, da eine interaktive Umsetzung erfolgen muss. Trotzdem
danke für den Hinweis.

Gruß
BrosBoss
...