Entwickler-Ecke

Netzwerk - TcpListener will nich funktionieren


C# - Mi 25.01.12 23:37
Titel: TcpListener will nich funktionieren
Hey ich bins... schon wieder.

Jetzt habe ich ein Problem mit meinem TcpListener und zwar dass er eine eingehende Verbindung nicht akzeptiert. Vll. liegt es daran dass ich es bisher nur auf meinem Rechner getestet habe, also mit "127.0.0.1", aber auch mit der Lokalen IP "192....". Auf jeden Fall liefert mir die "Pending()" Methode immer false zurück, auch wenn ich eine verbindung anlege.

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
private void AsyncListening()
        {
            while (AsyncAcceptingActive && !Cache.Main.Disposing && !Cache.Main.IsDisposed)
            {
                TcpClient client = new TcpClient();
                try
                {
                    TcpListener listener = new TcpListener(IPAddress.Any, 0);
                    listener.Start();
                    if (!listener.Pending()) continue;
                    client = listener.AcceptTcpClient(); //Diese Zeile wird nie erreicht
                    listener.Stop();
                }
                catch (Exception e) { System.Diagnostics.Debug.WriteLine(e);}

                NetworkStream stream = client.GetStream();
                byte[] buffer = new byte[1024];
                stream.Read(buffer, 0, buffer.Length);
                string s = encoder.GetString(buffer);
                if (!s.StartsWith("Sync::"))
                {
                    client.Close();
                    continue;
                }
//...

Außerdem erhalte ich ein paar Exceptions wenn ich die einzelnen Eigenschaften ansehen will (mit Debugger).
Die Anwendung soll später ein Client-Client verbindung erzeugen.
Zum Testen habe ich die .exe einfach zweimal gestartet (das eine mal natürlich ohne den Debugger) und bei der einen wird die Connect() Methode aufgerufen und bei beiden läuft asynchron dazu der TcpListener.

Kann es daran liegen, dass ich versuche zu meinem eigenen Pc zu verbinden?


C# - So 29.01.12 16:50

weis denn keiner eine Antwort? Ich verzweifel noch daran... Das Programm soll später mehrere Client-Client verbindungen aufbauen. Habs von verschiedenen PCs getestet und es funktioniert einfach nicht.


jaenicke - So 29.01.12 17:01

Ich habe gesehen, dass ein ähnliches Beispiel in der Doku steht, aber eigentlich kann es rein logisch so nicht funktionieren.

Mir Start startest du die Überwachung auf eingehende Verbindungen. Statt nun aber zu warten, dass tatsächlich eine Verbindung ankommt, prüfst du sofort ob direkt eine Verbindungsanforderung da ist. Woher soll die aber innerhalb der paar Millisekunden kommen?
Statt dann aber zu warten bis eine Verbindung angefordert wird, schmeißt du das Objekt weg und erstellst es neu. Da das ständig passiert, wäre es reiner Zufall, wenn genau in dem Sekundenbruchteil, in dem du wirklich eine Verbindung annehmen könntest, eine ankommt.

So wie ich es verstehe müsste es vom Prinzip her so aussehen:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
  TcpListener listener = new TcpListener(IPAddress.Any, 0);
  listener.Start();
  while (...)
  {
    if (listener.Pending())
    {
      client = listener.AcceptTcpClient();
      ...
    }
    ...
  }


Kha - So 29.01.12 17:03

Es gibt wahrscheinlich grundsätzlich wenige Fälle, in denen Pending Sinn macht. Wenn du blocken willst, benutze direkt AcceptTcpClient, ansonsten BeginAcceptTcpClient oder lagere die Schleife einfach in einen Hintergrundthread aus.


C# - So 29.01.12 20:31

Danke für eure Hilfe. Ich habe es mit BeginAccept() probiert. aber es will einfach nicht gehen... Ich bin nach dem Beispiel von MSDN gegangen
(http://msdn.microsoft.com/de-de/library/system.net.sockets.tcplistener.beginaccepttcpclient.aspx). Aber meine Callback-Methode wird nie aufgerufen.

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
 public void AsyncListening()
        {
            AsyncAcceptingActive = true;
            TcpListener listener = new TcpListener(IPAddress.Any, 0);
            listener.Start();
            listener.BeginAcceptSocket(ListenerAcceptingCallback, listener);
  }


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
private void ListenerAcceptingCallback(IAsyncResult state)
        {
            TcpClient client = ((TcpListener)state).EndAcceptTcpClient(state);
            ((TcpListener)state).Stop();
            if (!client.Connected)
            {
                NetworkStream stream = client.GetStream();
                byte[] buffer = new byte[1024];
                stream.Read(buffer, 0, buffer.Length);
//...
//...

So connecte ich:

C#-Quelltext
1:
2:
3:
4:
5:
        public void Connect(string name, IPAddress ip)
        {
            User user = new User { Name = name, State = UserState.Connecting, IP = ip};
            user.BeginConnect(ip, PORT, ConnectCallBack, user);
        }


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
private void ConnectCallBack(IAsyncResult state)
        {
                User user = state.AsyncState as User;
                if (user == nullreturn;
                if (!user.Connected) { user.State = UserState.WaitingForAccepting; Cache.Users.Add(user); return; }
                NetworkStream stream = user.GetStream();
                //...
    //...
        }

Das Connecten funktioniert auf jeden fall. Das habe ich mit einem Programm getestet.

Kann es daran liegen, dass mein Listener und mein Client in der gleichen Klasse arbeiten, bzw. gleichzeitig. Das Programm soll ja später anstehende Verbindungen annehmen und selber zu anderen PCs verbinden. Es ist immer das selbe Programm, sprich ich habe kein extra Server.


ujr - Mo 30.01.12 01:00

user profile iconC# hat folgendes geschrieben Zum zitierten Posting springen:


C#-Quelltext
1:
TcpListener listener = new TcpListener(IPAddress.Any, 0);                    


C#-Quelltext
1:
user.BeginConnect(ip, PORT, ConnectCallBack, user);                    



Was genau ist "PORT"? Vielleicht ist es besser, wenn Du erst einmal einen fest definierten Wert nimmst?

user profile iconC# hat folgendes geschrieben Zum zitierten Posting springen:

Das Connecten funktioniert auf jeden fall. Das habe ich mit einem Programm getestet.


Wie hast Du was getestet?

user profile iconC# hat folgendes geschrieben Zum zitierten Posting springen:

Kann es daran liegen, dass mein Listener und mein Client in der gleichen Klasse arbeiten, bzw. gleichzeitig.


Nö.


C# - Mo 30.01.12 11:26

PORT wird aus einer Settings datei ausgelesen. im prinizip kannst du es als konstante sehen. ich weis einfach nicht wo das problem liegt...


ujr - Mo 30.01.12 11:28

user profile iconC# hat folgendes geschrieben Zum zitierten Posting springen:
PORT wird aus einer Settings datei ausgelesen. im prinizip kannst du es als konstante sehen.


Fein, dann solltest Du den aber auch im Listener benutzen! Lies Dir in der Doku mal durch, was Port 0 bedeutet.


C# - Mo 30.01.12 12:01

hmm. ich meine ich hab das schon probiert. aber ich kann es nacher nochmal testen.

EDIT...
das mit port 0 weis ich.


C# - Di 07.02.12 21:58

So ich bin jetzt endlich mal wieder dazu gekommen das ganze zu Testen. Ich habe das Programm einfach auf 2 lokale PCs kopiert und gestartet. Beim Callback vom BeginConnect() erhalte ich dann die Exception:

Quelltext
1:
2:
{"Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die
hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat 192.168.2.114:7418"}

Hier der wichtigste Ausschnitt von meinem Connect-Callback

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
            try
            {
                User user = state.AsyncState as User;
                if (user == nullreturn;
                user.EndConnect(state); //Hier tritt die Exception auf
                if (!user.Connected) { user.State = UserState.WaitingForAccepting; Cache.Users.Add(user); return; }
                NetworkStream stream = user.GetStream();
//...


Mein Callback vom TcpListener wird gar nicht aufgerufen... BeginAccept() wird auf jeden Fall aufgerufen


C# - Mi 08.02.12 22:22

Hat jemand eine Idee warum mein Callback nicht aufgerufen wird? Eigentlich müsste alles passen...
Als Anhang hab ich mal die Datei in der das ganze statt findet.

P.S. bei Verbesserungsvorschlägen (wird es denke ich genug geben^^) bitte melden, danke.


C# - Do 09.02.12 23:18

Oh mann jetzt gibts in diesem Forum doch sooo viele Experten. Hat da wirklich keiner eine Idee? Ich werde noch irre... :eyecrazy: :eyecrazy:

///EDIT
kann es sein dass in dem neuen Thread, also bei BeginAcceptTcpClient(), eine interne Ausnahme ausgelöst wird, der Thread dadurch beendet wird, aber sich nach außen hin nicht meldet und das Programm ungestört fortfährt?
Das ****** Thema hab ich jetzt in 3 Foren gepostet und keiner hat ne Idee... :autsch: