C# Windows Service: UDP Listener - Hilfe beim Listener

Eddi85
Hallo Commuinty,

ich bräuchte etwas unterstützung beim umschreiben meines Codes in einen Windows Dienst (funktinoierende Applikation ist weiter unten zu sehen). Erstmal kurz zu der Aufgabe. Die Applikation nimm die UDP Pakete von unseren 2 USV Systemen entgegen und wertet diese aus. Sollte bei beiden Systemen im Paket der Code "0x0109" gefunden worden sein, heißt es das beide keine Strom haben. Wenn sich nach 1 min nix geändert hat, soll das Script die daran hängen Server geregelt runterfahren.
Wobei ich da schon ganz am anfang scheitere. Ich bräuchte nur etwas Unterstützung beim UDP Listener öffnen, Pakete auswerten, 1min warten.
Weiter unten ist auch meine aktuelle entwicklung zu sehen...

Vorhandene Applikation

C#-Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;


// Variablen

            string data;
            byte[] recieve = new Byte[1024];
            check controll = new check();
// erstelle UDP Listender
            IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 514);
            UdpClient connector = new UdpClient(ipep);
            IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
// erstelle Logfile
            FileStream logfile = new FileStream(@"c:\temp\ISOBot_log.txt",FileMode.OpenOrCreate, FileAccess.Write);
            StreamWriter stream = new StreamWriter(logfile);
            stream.BaseStream.Seek(0, SeekOrigin.End);
            stream.WriteLine(" ISOBot: Service Started \n");


// Führe Do-While solange aus, bis beide Systeme Strom haben
            do
            {
                while (controll.stat() == true) // Solange beide Strom haben
                {// Empfange UDP Pakte und wandele in ASCII String um
                    connector.Client.ReceiveTimeout = 0;
                    recieve = connector.Receive(ref sender);
                    data = Encoding.ASCII.GetString(recieve);

// Werte empfangene Pakete aus
                    controll.auswerten(data);
                }


// Setze den UDP listener Timeout auf 1 min
                stream.WriteLine(" SET Timeout 60 Sec \n");
                connector.Client.ReceiveTimeout = 60000;

// Werte weiterhin 1 min lang die UDP Paket aus, ob der Storm wieder kommt.
                do // Führe solange do-while bis zum Timeout
                {
                    try
                    {
                        recieve = connector.Receive(ref sender);
                        data = Encoding.ASCII.GetString(recieve);
                    }
                    catch
                    {// keine weitere Pakete erhalten, deshalb schreibe "Null" rein
                        data = null;
                    }

                    if (data != null)
                        controll.auswerten(data);

                } while (data != null); // verlasse do-while nach der 1 min



            } while (controll.stat() == true);
// führe solange aus bis beide USV Systeme Strom haben

// Wenn beide Systeme im Batteriebetrieb sind, liefert die funktion false zurück


// Schließe UDP Listener und schaltete alles ab.
            stream.WriteLine(" Beende alle Dienste \n");
            stream.Flush();
            stream.Close();
            connector.Close();
            controll.vmware(); // schalte Vmware Umgebung ab
            controll.sds_srv(); // Schalte Zentrales Storage ab

        }

CLASS CHECK

C#-Code:
using System;
using System.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;


namespace ISO_Bot
{
    class check
    {
        //Attribute
        private string USV1_IP = "192.168.10.14";
        private string USV2_IP = "192.168.10.15";
        private string stat_battery = "0x0109";
        private string stat_ok = "0x010A";
        private bool usv_stat1 = true, usv_stat2 = true;

//Methoden
// Funktion wertet erhaltenes Paket ASCII Zeichenkette aus
public void auswerten(string data)
        {
            if (data.Contains(stat_battery))
            {
                if (data.Contains(USV1_IP))
                    usv_stat1 = false;
                else if (data.Contains(USV2_IP))
                    usv_stat2 = false;
            }

            else if (data.Contains(stat_ok))
            {
                if (data.Contains(USV1_IP))
                    usv_stat1 = true;
                else if (data.Contains(USV2_IP))
                    usv_stat2 = true;
            }
        }

        public bool stat()
        {
            if (usv_stat1 == false && usv_stat2 == false)
                return false;
            else
                return true;
        }



        public void vmware()
        {
           // Console.WriteLine("Shutdown VM environment");
        }

        public void sds_srv()
        {
          //  Console.WriteLine("Shutdown Datacore Server");
        }

Dieser Teil hier unten läuft, lässt sich auch starten und stoppen aber sobald das Erste Paket ankommt und dieses ausgewertet wird, stürtzt dieser ab.
Die obere Applikation funktioniert einwandfrei.

aktueller Code (Windows Dienst) :

C#-Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
namespace ISO_Bot
{
publicpartialclassService1 : ServiceBase
{
private UDPsrv udpsrv;
public Service1()
{
InitializeComponent();
if (!EventLog.SourceExists("Application"))
EventLog.CreateEventSource("ISO - USV Monitor", "Application");
eventLog.Source = "ISO - USV Monitor";
}
protectedoverridevoid OnStart(string[] args)
{
eventLog.WriteEntry("In OnStart");

udpsrv = newUDPsrv();
Thread udpthread = newThread(newThreadStart(udpsrv.startsrv) );
udpthread.Start();
}
protectedoverridevoid OnStop()
{
eventLog.WriteEntry("In onStop.");
udpsrv.stopsrv();
}
}
}

CLASS UDPsrv

C#-Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace ISO_Bot
{
classUDPsrv
{
private bool srvstop;
private control check; // CHECK CLass wie schon oben verwendet

// Methode für um den Dienst zu starten
publicvoid startsrv()
{
srvstop = false;
byte[] receive = newbyte[1024];
string data;
check = newcontrol();

IPEndPoint ipep = newIPEndPoint(IPAddress.Any, 514);
UdpClient connect = newUdpClient(ipep);
IPEndPoint client = newIPEndPoint(IPAddress.Any, 0);

// führe solange aus bis der Dienst nicht gestop wird
while (! srvstop)
{
connect.Client.ReceiveTimeout = 0; // Setze erstmal Timeout auf unendlich

// Führe solange aus, bis der Dienst gestopt
while (! srvstop)
{
connect.Client.ReceiveTimeout = 0;
while(! srvstop)
{
receive = connect.Receive(ref client);
data = Encoding.ASCII.GetString(receive);
check.auswerten(data);

if (! check.stat()) // fals beide USV Systeme kein Storm haben, verlasse die While loop und stoppe den Dienst.
{
srvstop = true;
}
}
}
// Schlißene anschlißend den UDP Listener
connect.Close();
}


publicvoid stopsrv()
{
srvstop = true;
}
}
}

Liebe Grüße

Eddi85
Alf Ator
Um einen Windows-Dienst zu debuggen, ist es sinnvoll die Fehlermeldungen etc. in ein Logfile zu schreiben. Ich habe da mit NLog gute Erfahrungen gemacht.
Eddi85
Zitat von Alf Ator:
Um einen Windows-Dienst zu debuggen, ist es sinnvoll die Fehlermeldungen etc. in ein Logfile zu schreiben. Ich habe da mit NLog gute Erfahrungen gemacht.

Ich muss mich korrigieren. So wie der Windows Dienst da steht, funktioniert er und stürtzt auch nicht ab. Was nun das Problem ist, dass wenn bei USV Systeme das UDP Paket mit dem Code schicken und der dienst somit gestoppt hätte werden müssen läuft dieser einfach weiter... liegt das an den Threads???

Sende ich aber andere Code, stürtzt der Dienst mit der Error Code 1067 ab.

Jetzt wird für jede Verbindung ein Thread aufgemacht, die Variablen neu initialisiert und somit wird den nie der Status für beide USV Systeme auf false stehen?
pdelvo
Du wandelst die ankommenden Daten in einen string um(ASCII Encoding) und vergleichst ihn dann mit dem string "0x0109" oder "0x010A". Ich kenne das format zwar nicht, aber ich glaube das stimmt so nicht. bist du dir sicher, dass Diese zeichenketten gemeint sind?
Eddi85
Ja das sollte soweit richtig sein. Nach dem Umwandeln in ASCII string lässt sich die Nachricht aus der UDP paket auslesen und anschließend mit "contains" überprüfen ob der String "0x0109" sich in dem String befindet. Das mache ich ja auch schon bei meiner Consolen Applikation und da funktioniert es einwandfrei.

Sind denn die ersten Schritt soweit richtig ?

Thread -> UDP listener starten, ausführen solange sich die while loop selbst stop oder gestopt wird wenn ich den Dienst stoppe?
Innerhalb des thread brauch kein weiterer Thread erstellt werden, so wie es in diesem Aritkel gemacht wird?->  [Tutorial] Windows Services mit C#

Zitat von pdelvo:
Du wandelst die ankommenden Daten in einen string um(ASCII Encoding) und vergleichst ihn dann mit dem string "0x0109" oder "0x010A". Ich kenne das format zwar nicht, aber ich glaube das stimmt so nicht. bist du dir sicher, dass Diese zeichenketten gemeint sind?

Zitat von Alf Ator:
Um einen Windows-Dienst zu debuggen, ist es sinnvoll die Fehlermeldungen etc. in ein Logfile zu schreiben. Ich habe da mit NLog gute Erfahrungen gemacht.

Mit den Logfiles erstellen hat es leider nicht funktioniert. Aber ich denke ich weiß auch woran es liegt. Ich hab eben mal versuch mit Windows Eventlog zu debuggen...

Ich hab zuerst eine neue Funktion erstellt

C#-Code:
        public void writeEventLogWin(string strEvent)
        {
            if (!EventLog.SourceExists("Application"))
                EventLog.CreateEventSource("ISO - UDP Srv", "Application");

            EventLog MyEventLog = new EventLog();
            MyEventLog.Source = "ISO - UDP Srv";
            MyEventLog.WriteEntry(strEvent, EventLogEntryType.Warning);
        }

Und anschlißend hab ich den Code um ein paar Eventlog Einträge erweitert.
Dabei hab ich festgestellt, dass die Funktion startsrv nicht gestartet wird.

Wenn ich den Dienst Stoppe wird erst da der erste Eventlog erstellt, somit scheint alles was beim starten ausgeführt werden soll, nicht zu funktionieren. Oder liegt das an den threads??


aktuell Code von UDPsrv CLASS

C#-Code:
    class UDPsrv
    {
        private bool srvstop = false;
        private control check;

        public void startsrv()
        {
            [B]writeEventLogWin("Starte Dienst");[/B]
            byte[] receive = new byte[1024];
            string data;
            check = new control();

            IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 514);
            UdpClient connect = new UdpClient(ipep);
            IPEndPoint client = new IPEndPoint(IPAddress.Any, 0);
            [B]writeEventLogWin("Starte UDP Listener");[/B]

            connect.Client.ReceiveTimeout = 0;
            [B]writeEventLogWin("Setze Timeout auf 0");[/B]

            while(! srvstop)
                {
                try{
[B]                    writeEventLogWin("While Loop");[/B]
                    receive = connect.Receive(ref client);
                    data = Encoding.ASCII.GetString(receive);
                    check.auswerten(data);

[B]                    writeEventLogWin(data);[/B]
[B]                    writeEventLogWin("Vorher");[/B]
[B]                    writeEventLogWin(check.stat().ToString());[/B]

                    if (check.stat() == false)
                    {
[B]                        writeEventLogWin(check.stat().ToString());[/B]
                        srvstop = true;
                    }
                        }
                catch (Exception ex)
                    {
[B]                        writeEventLogWin(ex.ToString());[/B]
                    }
                }

[B]            writeEventLogWin(srvstop.ToString());[/B]
[B]            writeEventLogWin("Schließe UDP Listener automatisch");[/B]
            connect.Close();
        }


        public void stopsrv()
        {
[B]            writeEventLogWin("Schließe UDP Listener manuell");[/B]
            srvstop = true;
        }

        public void writeEventLogWin(string strEvent)
        {
            if (!EventLog.SourceExists("Application"))
                EventLog.CreateEventSource("ISO - UDP Srv", "Application");

            EventLog MyEventLog = new EventLog();
            MyEventLog.Source = "ISO - UDP Srv";
            MyEventLog.WriteEntry(strEvent, EventLogEntryType.Warning);
        }
    }
}
Eddi85
Fuck .... mein fehler, ich hab gerade gesehen das der Thread nicht gestartet wurde als ich eben etwas rum probiert habe.

C#-Code:
udpsrv = newUDPsrv();
Thread udpthread = newThread(newThreadStart(udpsrv.startsrv) );
udpthread.Start();

Nun konnte ich in den logs als letzten Eintrag die Ausgabe "While loop" sehen, das heißt er wartet auf auf daten... die bekommt er auch von mir, aber trotzdem rührt er sich da nicht weiter...

Ich konnte das Problem nun lösen... Das Problem war die Windows Firewall... bei meiner Consolen App wurde ich gefragt ob es in der Firewall als ausnahme aufgenommen werden sollte. Dieser Windows Dienst wurde blockiert... nachdem ich die Firewall deaktiviert hatte, funktionierte mein Dienst nun auch wie gewollt.
2 Dinge hätte ich noch... gibt es ein einfachen weg den Dienst automatisch in die Firewall als ausnahme aufnehmen zu lassen ?

Außerdem hab ich noch festgestellt, dass der Dienst weiter läuft obwohl das Script am enden angekommen ist... kann sich der Thread am Ende selbst schlißen?


Gruß
Eduard
Darth Maim
Das geht per cmd mit dem Befehlt netsh advfirewall firewall add rule. Guck dir da einfach mal die Parameter zu an, den Befehlt kannst du dann mit Hilfe der Process-Klasse ausführen.

Wenn dein Skript durchgelaufen ist, musst du nur srvstop auf true setzen, dann sollte sich dein Thread doch beenden. Alternativ setzt du bei dem Thread Background auf true, dann macht der Thread das selbst.

Darth Maim
Eddi85
Also wenn srvstop auf true setzen, wird der Verbindung auch beendet. Ich seh auch das der letzte Eventlog erstellt wird. Thread Background ist auch nicht aktiv... Trotzdem wird der Windows Dienst als gestartet angezeigt, was mich etwas verwundert da alles abgearbeitet ist.

Also ich hab eben noch udpthread.isbackground auf flase setzt

C#-Code:
        while(! srvstop)
        {
        try{
            writeEventLogWin("While Loop");
            receive = connect.Receive(ref client);
            data = Encoding.ASCII.GetString(receive);
            check.auswerten(data);

            writeEventLogWin(data);

                if (check.stat() == false)
                {
                srvstop = true;
                }
            }
            catch (Exception ex)
            {
            writeEventLogWin(ex.ToString());
            }
        }

        writeEventLogWin("ENDE WHILE");
        connect.Close();
        writeEventLogWin("Connection close");

In den Eventlogs seh ich auch den Eintrag "Connection close". Trotzdem ist der Dienst auf "gestartet".
gfoidl
Hallo Eddi85,

Zitat:
Trotzdem ist der Dienst auf "gestartet".

Du schließt nur die Verbindung, aber stoppst nicht den Windows-Dienst. Das sind 2 Paar verschiedene Schuhe.

mfG Gü
Eddi85
Okay, ich bin von ausgegangen das sich der Dienst beendet nachdem er alles abgearbeitet hatte. Wie krieg ich den Dienst nun selber gestoppt?
gfoidl
Hallo Eddi85,

du musst den Windows-Service stoppen, das geht mit ServiceBase.Stop();

mfG Gü
Eddi85
hmm... die Methode kennt er leider nicht.
Es wird, wie unten zu sehen, von ServiceBase geerbt.
Leider hab ich aber bei "Service1" nur folgende Methoden zu auswahl...
Run, Equals, MaxNameLength, ReferenceEquals und bei ServiceBase genau so.

Müsste der Aufruf in den thread oder in die OnStart Funktion?

C#-Code:
   public partial class Service1 : ServiceBase
    {
        private UDPsrv udpsrv;


        public Service1()
        {
            InitializeComponent();

            if (!EventLog.SourceExists("Application"))
                EventLog.CreateEventSource("ISO - USV Monitor", "Application");

            eventLog.Source = "ISO - USV Monitor";
        }

        protected override void OnStart(string[] args)
        {
gfoidl
Hallo Eddi85,

bitte ein bischen mehr Eigeninitiative, dann hättest du leicht  ServiceBase.Stop Method (System.ServiceProcess) gefunden und damit sollte es wohl lösbar sein. Andernfalls schau dir auch  [Tutorial] Windows Services mit C# an.


mfG Gü
Eddi85
Ich glaub ja das es die Methode gibt. Nur kennt sie anscheinend nicht das Visual Studio 2010... In der Anleitung wird sie auch nicht verwendet oder bin ich blind?

Ich hab es ja sehr ähnlich. eine bool variable die auf true gesetzt wird, somit wird die while schleife verlassen und dann wird der Socket geschlossen... bei mit mit connect.close(); und da wird der TCp listener gestopt (m_TcpListener.Stop();)
Deshlab kann ich dir nicht ganz folgen.
MartinH
Ich habe bei es meinen Services so:

C#-Code:
  public class MyThread : ThreadWorkerThread
{

    protected override void Run ()
    {
// Hier ist die Verarbeitung im Main Thread
    }

}

wird der Mainthread verlassen, dann ist auch der Service beendet.
Eddi85
Ich hab noch ein weiteres Problem enteckt. Und zwar wird der Dienst nicht sauber gestoppt wenn ich den Das mit der Dienst Steuerung "Beenden" oder "Neu starten" machen. Es wird die onStop funktion aufgerufen und der wert auf flase gesetzt. Somit muss die While schleife verlassen werden und der UDP Socket geschlossen werden, wobei der letzt Punkt nicht funktioniert. Nach dem While schleife mach ich noch eine ausgabe writeEventLogWin("ENDE WHILE"); & connect.Close();. Dieses taucht nicht auf. Wenn ich dann den neu wieder starten durch "starten" oder "neu starten" gibt es eine Fehlermeldung das der Socket nur einmal belegt werden kann und ich seh die letzte Ausgabe "Ende While" nicht in den Eventlogs. Ich vermute das problem liegt dann an der Receive methode... habt ihr eine Idee wie man das lösen könnte?
Ich hab schon dran gedacht, dass ganze mit thread und asyncronen Verbindungen zu machen also mit beginnreceive. Nur bin ich noch ein fortgeschrittener was C# und generell Objekt Orientierte Programmierung angeht. Und das ganze als Windows Service verkompleziert das für mich um einiges... Hätte ich ein ein Beispiel oder lust mir da ein weinig bei meinem Code unter die Arme zu greifen??
weismat
Du solltest vor dem Receive mittels

C#-Code:
connector.Client.Poll(SelectMode.SelectRead, timeout)

pruefen, ob Daten anstehen. Ansonsten solltest Du nach dem timeout pruefen, ob der Service sich beenden soll oder nicht.
 Doku kannst Du im Zweifel nochmals anschauen.
Eddi85
Hallo zusammen,

ich bin nun wieder ein Stück weiter gekommen. Und zwar habe ich das ganze nun mit Async Verbindungen realisiert. Pakete empfangen und auswerten funktioniert, die Dienste Steuerung Start, Stop und neu starten auch ohne Probleme. Ist es dann noch nötig mit thread zu arbeiten?
Könnte ich nicht einfach den ganzen Code nun in OnStart() schreiben ?

C#-Code:
namespace ISO_SysLog
{
    class UdpState
    {
        public UdpClient udp;
        public IPEndPoint ipep;
    }

     class UDPsrv
     {
        private control check = new control();
        private int _Port = 514;
        private UdpClient udp = null;

        public void start()
        {
            IPEndPoint ipep = new IPEndPoint(IPAddress.Any, _Port);
            udp = new UdpClient(ipep);

            udp.BeginReceive(new AsyncCallback(doReceive), new UdpState() { ipep = ipep, udp = udp });
        }

        public void stop()
        {
            writeEventLogWin("Schließe UDP Listener");
            udp.Close();
        }

        private void doReceive(IAsyncResult iar)
        {
            try
            {
                //Get the received message
                UdpClient udp = (UdpClient)((UdpState)(iar.AsyncState)).udp;
                IPEndPoint ipep = (IPEndPoint)((UdpState)(iar.AsyncState)).ipep;

                byte[] receive_bytes = udp.EndReceive(iar, ref ipep);

                writeEventLogWin("Empfange Daten");

                // Handle the received message
                check.auswerten(Encoding.ASCII.GetString(receive_bytes));
                writeEventLogWin(Encoding.ASCII.GetString(receive_bytes));

                //Star listening for a new Message
                udp.BeginReceive(new AsyncCallback(doReceive), new UdpState() { ipep = ipep, udp = udp });
            }
            catch (SocketException err)
            {
                writeEventLogWin(err.Message);
                writeEventLogWin(err.ErrorCode.ToString());
            }

        }

Sollte ich denn nun hierbei auch mit der Poll Methode machen??
quasi die befehle in ein IF ELSE verschachteln?

C#-Code:
IF(check.state() == false)
{
     udp.Client.Poll(60000, SelectMode.SelectRead;
     byte[] receive_bytes = udp.EndReceive(iar, ref ipep);
     check.auswerten(Encoding.ASCII.GetString(receive_bytes));

     IF (check.state() == false)
     udp.close();
     ELSE
     udp.BeginReceive(new AsyncCallback(doReceive), new UdpState() { ipep = ipep, udp = udp });
}
ELSE
{
byte[] receive_bytes = udp.EndReceive(iar, ref ipep);
check.auswerten(Encoding.ASCII.GetString(receive_bytes));
udp.BeginReceive(new AsyncCallback(doReceive), new UdpState() { ipep = ipep, udp = udp });
}

* Das würde heißen, wenn der Status false ist (Was soviel heißt wie, dass beide USV Systeme sich im Batterie Modus befinden), soll er 60 sec warten ob sich der Status nochmal ändert um wie gewohnt weiter auf dem Port 514 zu lauschen, ansonsten wird die Verbindung geschlossen. Anschließen soll er, nach dem schließen, noch ein paar Befehle ausführen... an welcher Stelle könnte man diese anbringen?
Also er soll anschließend 2-3 Powershell scripte ausführen...

Grüße
Eddi
weismat
Den Poll brauchst Du nur, wenn Du synchron arbeitest.
BeginReceive arbeitet asynchron implizit mit einem Thread aus dem Threadpool, der Deinen Code ausfuehrt, wenn Daten kommen.
Eddi85
Zitat von weismat:
Den Poll brauchst Du nur, wenn Du synchron arbeitest.
BeginReceive arbeitet asynchron implizit mit einem Thread aus dem Threadpool, der Deinen Code ausfuehrt, wenn Daten kommen.

Okay. Womit könnte ich denn mein Ziel erreichen?

Ich hab nun erstmal eine abfrage rein gebastellt die überprüft ob check.state() == false, wenn es der Fall ist soll er der Socket schließen. ansonsten soll er ein AsyncCallback machen und einen neuen beginnReceive starten.

Es wird doch irgendwie möglich sein nun für 50 sekunden weiterhin Packete empfangen und auswerten, wenn sich der Status anschließend nicht geändert hat soll er erst der Socket schließen.

Nur beendet sich der Dienst nicht, wenn der Sockt geschlossen wird... dabei ist die Start Funktion am ende angelangt. Ich Probiers dann mal mit dem Main Thread, wie vorhin schon vorgeschlagen.
Wo kommt er denn bei mir hin? Mir ist das noch nicht ganz klar wie ich den nutze.

Zitat von MartinH:
Ich habe bei es meinen Services so:

C#-Code:
  public class MyThread : ThreadWorkerThread
{

    protected override void Run ()
    {
// Hier ist die Verarbeitung im Main Thread
    }

}

wird der Mainthread verlassen, dann ist auch der Service beendet.

So habe ich das auch. Ich hab eine neue Klasse erstellt, die heißt UDPsrv darin hab ich 2 public Funktion start() und stop(). Nur hab ich keine Vererbung von ": ThreadWorkerThread"

Darin ist der ganzen Code, wie oben zum teil auch zu sehen. wenn also nun check.stat() als Rückgabe Wert false hat, mach ich ein "this.stop();"
somit wird die eigene Stop Funktion aufgerufen und die schließt das Socket und macht kein AsyncCallback mehr, somit bin ich am ende der start() funktion angelegt. Nur ist der Dienst aber weiterhin noch aktiv, Socket ist aber richtig geschlossen worden.

Nur habe ich jetzt nix weiteres mehr in der OnStart Funktion stehen nach dem thread.start().

C#-Code:
protectedoverridevoid OnStart(string[] args)
{
eventLog.WriteEntry("In OnStart");

udpsrv = newUDPsrv();
Thread udpthread = newThread(newThreadStart(udpsrv.startsrv) );
udpthread.Start();
}

Ich hab jetzt mal die Onstart() Funktion erweitert, so wie in dem Beispiel bei Microsoft  Gewusst wie: Erstellen und Beenden von Threads.

C#-Code:
while (! udpthread.IsAlive) ;

thread.Sleep(1);

udpthread.Join();
eventlog.WirteEntry("Thread: UDPsrv Thread has Terminated");

anschließend konnte ich den Eventlogs schon die die letzte Ausgabe sehen "Thread: UDPsrv Thread has Terminated" obwohl der gestartete Thread noch aktiv ist, der UDP Listener läuft und auch Daten ganz normal ausgewertet werden. Das würde auch erklären wieso sich der Dienst nicht beendet. Er läuft einfach weiter ob der Thread noch aktiv ist oder nicht.