Forum: PC-Programmierung c# TcpListener mehrere IP-Adressen


von Bernd (Gast)


Lesenswert?

Hallo

Ich habe folgendes Problem:

Ich bin dabei einen TCPIP Server in C# (Visual Studio) zu schreiben. Er 
funktioniert auch genau so wie ich mir das alles vorstelle. Sobald ich 
aber eine zweite IP-Adresse unter Windows 10 hinzufüge funktioniert der 
untenstehende Sourccode nicht mehr. Wie gesagt mit nur einer 
Netzwerkadresse funktioniert alles wunderbar. Auch wenn ich 
IPAddress.Any durch meine Ip Adresse, oder durch "0.0.0.0" ersetze kommt 
das Programm aus listener.AcceptTcpClient() nicht mehr zurück. Erst wenn 
ich, sogar zur Programmlaufzeit, meine zweite IP Adresse aus Windows 
entferne läuft alles einwandfrei.


TcpListener listener = new TcpListener(IPAddress.Any, Port);
listener.Start();
if (!listener.Pending()) break; //switch case, deshalb das break;
TcpClient client = listener.AcceptTcpClient();


Hat da jemand eine Idee woran es liegen könnte oder sehe ich den Wald 
vor lauter Bäumen nicht?

Im Voraus schon mal danke

von Dirk K. (merciless)


Lesenswert?

https://mycsharp.de/forum/threads/121536/wieso-bleibt-accepttcpclient-beim-tcp-listener-haengen

Zitat: "Wie Du der Dokumentation entnehmen kannst, ist AcceptTcpClient 
eine blockierende Methode. Diese blockt solange, bis sich ein Client 
verbindet - und blockt danach wieder.
...
Ergo: asynchron programmieren und die asynchrone Methode verwenden, wie 
es auch in der Dokumentation verwiesen ist."

https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.tcplistener.accepttcpclient?view=net-6.0

Zitat: "AcceptTcpClient is a blocking method that returns a TcpClient 
that you can use to send and receive data. Use the Pending method to 
determine if connection requests are available in the incoming 
connection queue if you want to avoid blocking.

Use the TcpClient.GetStream method to obtain the underlying 
NetworkStream of the returned TcpClient. The NetworkStream will provide 
you with methods for sending and receiving with the remote host. When 
you are through with the TcpClient, be sure to call its Close method. If 
you want greater flexibility than a TcpClient offers, consider using 
AcceptSocket."

merciless

von Dirk K. (merciless)


Lesenswert?

Für mein Verständnis musst du sowas in der Art machen:
1
TcpListener listener = new TcpListener(IPAddress.Any, Port);
2
listener.Start();
3
while (true)
4
{
5
  TcpClient client = listener.AcceptTcpClient();
6
  clientThread = new Thread(...);
7
  clientThread.Start();
8
}

merciless

von Bernd (Gast)


Lesenswert?

Ja das habe ich auch gedacht. Grundsätzlich funktioniert ja auch alles 
super.

Die Probleme fangen dann an wenn dem Rechner zwei IP Adressen vergeben 
werden. Dann kommt die Funktion TcpClient client = 
listener.AcceptTcpClient() nämlich gar nicht zurück. Auch dann nicht 
wenn ich nicht anstatt TcpListener(IPAddress.Any, Port) 
TcpListener(IPAddress.Parse("xxx.xxx.xxx.xxx", Port) definiere. Also die 
korrespondierende Adresse.

Wenn ich zunächst nur eine (die korrespondierende) Adresse am Rechner 
eingestellt habe ist alles gut, funzt einwandfrei. Auch wenn ich ihm 
dann die Zweite gebe ist noch alles gut. Boote ich den Rechner aber dann 
mit beiden Netzwerkadressen neu, bleibt er wieder in der 
AcceptTCPClient() Methode hängen und wartet das ein Port geöffnet wird, 
was auch definitiv versucht wird.

Ich kann mir kaum vorstellen das ich der erste bin dem das auffällt, 
aber wahrscheinlich bin ich der Erste der zumindest im Moment noch keine 
wirkliche Lösung dafür hat.
Aber ich werde heute mal Deinen Ansatz mit den asynchronen Methoden 
testen.

Trotzdem zunächst mal vielen Dank.

von Ozvald K. (Firma: Privat) (ozvaldk)


Lesenswert?

Bernd schrieb:
> Die Probleme fangen dann an wenn dem Rechner zwei IP Adressen vergeben
> werden.

Ich hatte vor x Jahren eine Anwendung entwickelt, wo beim PC bis zu 5 
IP-Adressen vergeben wurden, und auch soviel Instanzen vom Programm 
gleichzeitig gelaufen sind, jeder Instanz mit eigener IP-Adresse. Es hat 
tadellos funktioniert. Das Konzept sieht so aus: Das Hauptprogramm 
(Winform) hat einen Thread erzeugt wo der Listener gelaufen ist. Dieser 
Thread hat dann die TCP Clients, alle in weiteren eigenen Threads bei 
eigehender Verbindung erstellt. Eine Instanz vom Programm hat mit 
mehreren Clients (bis 50) kommuniziert. In Threads wurden Events 
definiert wodurch im Hauptprogramm die entsprechende Funktionen 
aufgerufen und eingehende Informationen weiter gereicht wurden. Als 
Basis von dieser Client-Server Kommunikation habe das Beispiel damals 
von der Microsoft Seite genommen. Ich wollte hiermit nur sagen, dass 
Dein Vorhaben funktioniert. (funktionieren kann)

Edit: der Knackpunkt ist den Listener in eigenem Thread zu erzeugen, 
damit das Hauptprogramm dadurch nicht blockiert wird

: Bearbeitet durch User
von Dirk K. (merciless)


Lesenswert?

Hier gibt es ein umfangreiches Tutorial,
vielleicht hilft dir das weiter:

https://mycsharp.de/forum/threads/19670/tutorial-client-server-komponente-ueber-tcp-sockets

merciless

von Bernd (Gast)


Lesenswert?

Ozvald K. schrieb:
> Edit: der Knackpunkt ist den Listener in eigenem Thread zu erzeugen,
> damit das Hauptprogramm dadurch nicht blockiert wird

Ja das habe ich gemacht. Ohne Erfolg


Dirk K. schrieb:
> Hier gibt es ein umfangreiches Tutorial,
> vielleicht hilft dir das weiter:
>
> 
https://mycsharp.de/forum/threads/19670/tutorial-client-server-komponente-ueber-tcp-sockets

Ich habe jetzt das Beispiel fast 1:1 so übernommen. Dort wird ja auch 
ein Thread erzeugt für den Listener (so wie Ozvald auch geschrieben 
hat). Hat aber auch nicht funktioniert.

Aber wenn ich die Firewall abschalte dann funktioniert es einwandfrei. 
Komischerweise habe ich den entsprechenden Port schon vor mehreren Tagen 
freigegeben. Was ich aber noch nicht verstehe ist warum es von Anfang an 
funktioniert hat mit einer Ip Adresse, bei zweien aber nicht mehr.

Aber vielen Dank für die Hilfe, bin ja jetzt schon ein ganzes Stück 
weiter und man wird ja nicht dümmer :-)

von Sascha W. (sascha-w)


Lesenswert?

Vielleicht liegt's daran das WIN (damit arbeitest du doch?) für jedes 
Netzwerk einen Typ pflegt (privat, öffentlich) womit sich per Default 
schon mal unterschiedliche Firewallregeln ergeben. Ein neues Netz ist 
erst mal nicht privat und die meisten eingehenden Verbindungen werden 
blockiert.

Sascha

von Bernd (Gast)


Lesenswert?

Ja genau das war auch das Problem. Jetzt läuft es sehr stabil durch.

Warum das mit einer Netzwerkadresse von Anfang an funktioniert hat, aber 
mit zwei Adressen nicht, ist mir nach wie vor schleierhaft.
Vielleicht reicht dafür mein geistiger Horizont auch nicht :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.