Laden...

TCP Server hängt sich auf

Erstellt von progi123 vor 13 Jahren Letzter Beitrag vor 13 Jahren 2.477 Views
progi123 Themenstarter:in
71 Beiträge seit 2008
vor 13 Jahren
TCP Server hängt sich auf

Heyho,

bei dem unten stehenden Server gibt es das Problem, dass die CPU-Auslastung auf 100% steigt wenn der Client verschwunden ist. Es wird keine Exception geworfen und wenn man SendMessageBack ausschaltet hilft es auch nicht weiter. Habt ihr einen Tipp für mich?


using System;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;

namespace TCPServer
{
    class Server
    {
        TcpListener tcpListener;
        Thread listenThread;

        public void Start()
        {
            tcpListener = new TcpListener(IPAddress.Any, 2000);
            listenThread = new Thread(new ThreadStart(ListenForClients));
            listenThread.Start();
        }

        private void ListenForClients()
        {
            tcpListener.Start();

            while (true)
            {
                TcpClient client = tcpListener.AcceptTcpClient();
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
        }

        private void HandleClientComm(object client)
        {
            while (true)
            {
                TcpClient tcpClient = (TcpClient)client;

                if (tcpClient.Connected)
                {
                    NetworkStream clientStream = tcpClient.GetStream();

                    byte[] message = new byte[tcpClient.ReceiveBufferSize];
                    int bytesRead = 0;

                    do
                    {
                        try
                        {
                            bytesRead = clientStream.Read(message, 0, tcpClient.ReceiveBufferSize);
                        }
                        catch (Exception)
                        {
                            break;
                        }

                        if (bytesRead == 0) break;

                        String result = ASCIIEncoding.ASCII.GetString(message, 0, bytesRead);
                        String ip = tcpClient.Client.RemoteEndPoint.ToString();

                        Console.WriteLine(ip + " " + result);

                        Thread sendThread = new Thread(new ParameterizedThreadStart(SendMessageBack));
                        sendThread.Start(tcpClient);

                        Thread importThread = new Thread(new ParameterizedThreadStart(ImportInDB));
                        importThread.Start(result);

                    } while (clientStream.DataAvailable);

                }
            }
        }

        private void SendMessageBack(object client)
        {
            try
            {
                TcpClient tcpClient = (TcpClient)client;
                NetworkStream clientStream = tcpClient.GetStream();

                byte[] message = ASCIIEncoding.ASCII.GetBytes("OK");
                clientStream.Write(message, 0, message.Length);
                clientStream.Flush();
            }
            catch (Exception)
            {
                Console.WriteLine("Client ist verschwunden.");
            }
        }

        private void ImportInDB(object data)
        { 
            //kommt noch
        }
    }
}

L
416 Beiträge seit 2008
vor 13 Jahren

Wird wahrscheinlich an deiner while(true) Schleife liegen. Verwende lieber Events wie hier zb: TCPComponents.

progi123 Themenstarter:in
71 Beiträge seit 2008
vor 13 Jahren

Danke für den Hinweis. Hab das jetzt so gelöst:


if (tcpClient.Connected)
{
       //....
}
else 
{
       break;
}

Wird wahrscheinlich an deiner while(true) Schleife liegen. Verwende lieber Events wie hier zb: TCPComponents.

Ein Eventbasierter Server wäre auch ganz interessant. Schau ich mir mal an.

U
1.688 Beiträge seit 2007
vor 13 Jahren

Hallo,

korrekt wäre wahrscheinlich, statt


if (bytesRead == 0) break;

dies zu verwenden:


if (bytesRead == 0) return;

61 Beiträge seit 2009
vor 13 Jahren

Auf keinen Fall so lösen!!! ^^

Danke für den Hinweis. Hab das jetzt so gelöst:

  
if (tcpClient.Connected)  
{  
       //....  
}  
else   
{  
       break;  
}  
  

Denn ich habe das schon sehr oft durchprobiert.
Selbst wenn der Client auf der anderen Seite Close() gemacht hat, steht bei mit am Server immer noch tcpClient.Connectet == true.

Ich habe das dann so gelöst, dass mein Client einen Byte-Wert schickt und dadurch dem Server signalisiert, dass er jetzt die Verbindung trennt.

Nur habe ich dabei das Problem: Wenn der Server beendet wird, dann empfängt der Client keine Daten. Ich prüfe dazu immer networkStream.DataAvailable...

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.

P
67 Beiträge seit 2008
vor 13 Jahren

Das was ujr geschrieben hat ist (halb) richtig. Sobald sich ein (verbindungsorientierter) Client trennt - und dieser dann Shutdown() aufruft - kommt auf der gegenseite die Receive()-Methode durch und gibt die erhalten Byte-Anzahl von 0 zurück. Die 0 signalisiert eine Trennung der Verbindung.

Selbst wenn der Client auf der anderen Seite Close() gemacht hat, steht bei mit am Server immer noch tcpClient.Connectet == true.

Klar. Irgendwie muss der Client ja dem Server signalisieren das er weg ist. Der Server wird auch weiterhin mit dem Client verbunden sein, aber nicht andersrum (weiteres senden würde zu SocketExceptions führen).

Bitte schreien wenn ich mich irre.

Religionskriege sind Konflikte zwischen erwachsenen Menschen, bei denen es darum geht, wer den cooleren, imaginaeren Freund hat