Laden...

[GELÖST] Server schließt sich immer nach getrennter Verbindung

Erstellt von KevinHappy vor 8 Jahren Letzter Beitrag vor 8 Jahren 2.432 Views
K
KevinHappy Themenstarter:in
41 Beiträge seit 2015
vor 8 Jahren
[GELÖST] Server schließt sich immer nach getrennter Verbindung

Hallo,

ich habe mir das Tutorial "Client-/Server-Komponente über TCP-Sockets" hier auf der Seite gerade angeschaut und wollte diesen Code für mich Optimieren.

Bissher habe ich diesem Code:


    /// <summary>
    /// Zusammenfassung für den Server
    /// </summary>
    public class Server
    {
        /// <summary>
        /// Port, auf dem der Server auf Clientverbindungen wartet
        /// </summary>
        public const int serverListenPort = 10000;

        /// <summary>
        /// Anzahl Millisekunden in Warteschleifen
        /// </summary>
        public const int sleepTime = 200;

        /// <summary>
        /// Der Haupt-Thread
        /// </summary>
        private Thread mainThread;

        /// <summary>
        /// IP-Adresse, an der auf Verbindungen gewartet werden soll.
        /// Standardmässig wird auf allen Schnittstellen gewartet.
        /// </summary>
        public IPAddress ipAddress = IPAddress.Any;

        /// <summary>
        /// Der Standardkonstruktor richtet den Thread ein, welcher
        /// anschliessend auf Client-Verbindungen wartet.
        /// </summary>
        public Server()
        {
            // Hauptthread wird instanziiert ...
            mainThread = new Thread(new ThreadStart(this.mainListener));
            // ... und gestartet
            mainThread.Start();
        }

        /// <summary>
        /// Haupt-Thread, wartet auf neue Client-Verbindungen
        /// </summary>
        private void mainListener()
        {
            // Alle Netzwerk-Schnittstellen abhören
            TcpListener listener = new TcpListener(ipAddress, serverListenPort);
            System.Console.WriteLine("Listening on port " + serverListenPort + "...");
            try
            {
                // Verbindungsannahme aktivieren
                listener.Start();
                // Warten auf Verbindung
                while (!listener.Pending()) { Thread.Sleep(sleepTime); }
                // Verbindung annehmen
                Socket newSocket = listener.AcceptSocket();
                // Mitteilung bzgl. neuer Clientverbindung
                System.Console.WriteLine("Neue Client-Verbindung (" +
                            "IP: " + newSocket.RemoteEndPoint + ", " +
                            "Port " + ((IPEndPoint)newSocket.LocalEndPoint).Port.ToString() + ")");
            }
            catch (Exception ex)
            {
                throw new Exception("Fehler bei Verbindungserkennung", ex);
            }
        }
    }

Ich möchte nun aber den Server starten und dann soll er laufen, bis man ihn wieder manuell schließt. Quasi eine Endlosschleife. Zuerst möchte ich, dass das ganze mit einer Verbindung stabil funktioniert.

Wie bekomme ich das hin?

Edit:
Habe jetzt

for (; ; ){...}

genommen.

--
Vielen Dank

LG
Kevin

16.806 Beiträge seit 2008
vor 8 Jahren

Deine in den Startbeitrag hinein editierte Lösung ist nicht gerade sauber.
Ich sehe am Code Deines Servers auch nicht, wieso es nicht dauerhaft laufen sollte.
Vermutlich ist es ein Fehler, wie Du die Server-Klasse nutzt.

K
KevinHappy Themenstarter:in
41 Beiträge seit 2015
vor 8 Jahren

Hi Abt,

ich erstelle einfach beim Programmstart ein Objekt von der Server Klasse.
Mehr passiert hier nicht. Wenn der Client geschlossen wird, schließt sich der Server.

--
Vielen Dank

LG
Kevin

2.298 Beiträge seit 2010
vor 8 Jahren

Das Grundproblem liegt aus meiner Sicht darin, dass du nur einen Client annimmst. Wenn der Client disconnected wird auch dein Thread verlassen. - Bisher dacht ich immer, dass das vorher schon passiert - Aber vielleicht ist es ja auch so.

Wie sieht denn deine Program.cs aus?

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

K
KevinHappy Themenstarter:in
41 Beiträge seit 2015
vor 8 Jahren

So:

Das Sleep ist einfach nur drin, dass ich seh was in der Console steht, bevor der Server beendet wird.


    class Program
    {
        static void Main(string[] args)
        {
            Server srv = new Server();
            System.Threading.Thread.Sleep(10000);
        }
    }

--
Vielen Dank

LG
Kevin

2.298 Beiträge seit 2010
vor 8 Jahren

Schön wäre es, wenn du deine Lösung noch posten würdest.

// EDIT
Statt dem Thread.Sleep() solltest du eher Console.ReadLine() oder ähnliches verwenden. Dann bleibts auch stehen, wenn du mal abgelenkt bist. 😃

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

K
KevinHappy Themenstarter:in
41 Beiträge seit 2015
vor 8 Jahren

Edit:
Habe jetzt

for (; ; ){...}  

genommen.

Die Lösung steht schon im Startthread.
Das Sleep kommt auch wieder raus, war nur zu Testzwecken.

--
Vielen Dank

LG
Kevin

2.298 Beiträge seit 2010
vor 8 Jahren

Ich versteh die Lösung nicht. - Also denke ich, wird auch kein anderer wissen was du nun mit der For-Schleife anfängst.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

K
KevinHappy Themenstarter:in
41 Beiträge seit 2015
vor 8 Jahren

Die Lösung ist einfach eine Endlosschleife.


public void Process()
        {
            MySQL mysql = new MySQL();
            DateTime now = DateTime.Now;
            MemoryStream mem = new MemoryStream();// Empfangspuffer
            byte[] buffer = new byte[BufferSize];
            int TimeOut = 0;
            instanceOfClass.newMessage("Server gestartet");

            //while (TimeOut < (10 * 1000 / SleepTime))
            for (; ; )
            {
                //Console.WriteLine("1 - jhadbfhibsdb");
                mem.Seek(0, SeekOrigin.Begin);
                mem.SetLength(0);
                while (socket.Available > 0)
                {
                    //Console.WriteLine("2 - jhadbfhibsdb");
                    //Byte[] buffer = new byte[bytesAvailable];
                    int bytesRead = socket.Receive(buffer, buffer.Length, SocketFlags.None);
                    if (bytesRead <= 0) continue;
                    mem.Write(buffer, 0, bytesRead);
                    //instanceOfClass.Receive(buffer);
                    // Alles zurücksetzen
                }
                if (mem.Length > 0)
                {
                    //Console.WriteLine("3 - jhadbfhibsdb");


                    //if (System.Text.Encoding.ASCII.GetString(mem.ToArray(), 0, 4) == "quit")
                    //{
                    //    instanceOfClass.closeConnection();
                    //    //socket.Close();
                    //    Console.WriteLine("Client (" + socket.RemoteEndPoint + ") wurde vom Server getrennt.");
                    //}
                    if (System.Text.Encoding.ASCII.GetString(mem.ToArray(), 0, 9) == "newvendor")
                    {
                        string stream = System.Text.Encoding.ASCII.GetString(mem.ToArray());
                        string[] split = stream.Split(new Char[] { '|' });
                        mysql.insertVendor(split[1], split[2], split[3], split[4]);

                        Console.WriteLine("Ein neuer Lieferant (" + split[1] + ") wurde angelegt. " + now.ToString("dd.MM.yyyy HH:mm"));
                        instanceOfClass.Send(System.Text.Encoding.ASCII.GetBytes("erfolgreich"));
                    }
                    else if (System.Text.Encoding.ASCII.GetString(mem.ToArray(), 0, 17) == "insertordernumber")
                    {
                        string stream = System.Text.Encoding.ASCII.GetString(mem.ToArray());
                        string[] split = stream.Split(new Char[] { '|' });
                        mysql.insertIntoDatabase(split[1], split[2]);

                        Console.WriteLine("Der Artikel (" + split[1] + ") wurde für den Lieferant (" + split[2] + ") hinzugefügt. " + now.ToString("dd.MM.yyyy HH:mm"));
                        instanceOfClass.Send(System.Text.Encoding.ASCII.GetBytes("erfolgreich"));

                    }
                    //Console.WriteLine("send {0} bytes",mem.Length);
                    //instanceOfClass.Receive(mem.ToArray());
                    mem.Seek(0, SeekOrigin.Begin);
                    mem.SetLength(0);
                    TimeOut = 0;

                    //Console.WriteLine("4 - jhadbfhibsdb");
                }
                else
                {
                    TimeOut++;
                    Thread.Sleep(SleepTime);
                }
            }
            instanceOfClass.closeConnection();
            socket.Close();
            socket = null;
            serverThread.Abort();
        }

--
Vielen Dank

LG
Kevin

M
171 Beiträge seit 2012
vor 8 Jahren

Statt for(;;) würde ich eher sowas wie while(!shutdown) nehmen, dann kannst du den Server auch gezielt beenden indem du das shutdown flag setzt. Ansonsten passts doch. Der ganze Kram in if (mem.Length > 0) geht auch einfacher, wenn Du einen TcpListener / TcpClient und dazu StreamReader/StreamWriter verwendest.