Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[NET]Multicastsocket schließen

0 views
Skip to first unread message

Mario Schattschneider

unread,
Sep 21, 2004, 5:27:29 AM9/21/04
to
Hallo,

ich stehe vor folgendem Problem.
Anwender sollen sich in meiner Anwendung an jeweils verschiedenen
Multicastgruppen anmelden können, um von dort Pakete zu empfangen.

Es soll aber bisher nur eine Multicast Adresse abonierbar sein.
Demzufolge muß ich die alte Multicastgruppe verlassen, was scheinbar
auch mit einem socket.leaveGroup(InetAddress.getByName(oldAdress));
funktioniert.

Wenn ich versuche das Socket zu schließen erhalte ich folgende
Fehlermeldung:
java.net.SocketException: socket closed
at java.net.PlainDatagramSocketImpl.receive(Native Method)
at java.net.DatagramSocket.receive(DatagramSocket.java:711)
at notemsgTransport.MulticastRec.run(MulticastRec.java:67)
at java.lang.Thread.run(Thread.java:534)

Die Zeile 67 enhält folgendes: socket.receive(packet);

Das ganze hier läuft in der run Methode.
Beim Adressaustausch setzte ich das MutlticastThread = null und starte
es entsprechend neu. Nur würde ich gern das alte Socket sauber
schließen wollen.
...
while (MultiCastThread != null) {
byte[] buf = new byte[2048];
DatagramPacket packet = new DatagramPacket(buf, buf.length);

socket.receive(packet);
rb.put(packet);

Vielleicht hat jemand einen Tip.

Vielen Dank im Vorraus

Viele Grüße aus dem Norden

Mario Schattschneider

Gerald Mixa

unread,
Sep 21, 2004, 9:38:30 AM9/21/04
to
Mario Schattschneider wrote:

> Hallo,


ließen wollen.
> ...
> while (MultiCastThread != null) {
> byte[] buf = new byte[2048];
> DatagramPacket packet = new DatagramPacket(buf, buf.length);
>
> socket.receive(packet);
> rb.put(packet);
>
> Vielleicht hat jemand einen Tip.
>
> Vielen Dank im Vorraus
>
> Viele Grüße aus dem Norden
>
> Mario Schattschneider

Wo verläßt du die Multicastgruppe?
Meines Wissens nach ist ein socket.leave notwendig, da man sonst in der
Gruppe registriert bleibt. Beispiel Siehe JDK Doc!. SocketClosed würde
meiner Meinung nach auch passen. Da der socket nicht mer existiert,
allerdings nachwievor als Empfänger registriert ist.

MfG aus dem tiefsten Süden!
Gerald
--
substitute the u by y to send me a mail

Jochen Theodorou

unread,
Sep 21, 2004, 11:46:47 AM9/21/04
to
Mario Schattschneider schrieb:
> Hallo,
>
[...]

> Wenn ich versuche das Socket zu schließen erhalte ich folgende
> Fehlermeldung:
> java.net.SocketException: socket closed
> at java.net.PlainDatagramSocketImpl.receive(Native Method)
> at java.net.DatagramSocket.receive(DatagramSocket.java:711)
> at notemsgTransport.MulticastRec.run(MulticastRec.java:67)
> at java.lang.Thread.run(Thread.java:534)
>
> Die Zeile 67 enhält folgendes: socket.receive(packet);

Das ist nachdem du den Socket geschlossen hast. Du kannst von einem
gechlossenen Socket nix empfangen also kommt eine Exception.

Gruss theo

Mario Schattschneider

unread,
Sep 22, 2004, 3:53:33 AM9/22/04
to
Gerald Mixa schrieb:

Hallo Gerald,

>Mario Schattschneider wrote:
>Wo verläßt du die Multicastgruppe?

Den Code habe ich nicht gepostet.

Aber mit der Methode setze ich die neue Adresse, und verlasse vorher
die Gruppe.

public void setIPAddress(String address) {
// ToDO Fehlerbehandlung

MultiCastThread = null;
if (MultiCastThread == null) {
try {
socket.leaveGroup(InetAddress.getByName(ipAddress));
//Fehler
socket.close();
}
catch (IOException ex) {
ex.printStackTrace();
System.out.println(ex.getMessage());
}
this.ipAddress = address;
MultiCastThread = new Thread(this);
MultiCastThread.start();
}
}

>Meines Wissens nach ist ein socket.leave notwendig, da man sonst in der
>Gruppe registriert bleibt. Beispiel Siehe JDK Doc!. SocketClosed würde
>meiner Meinung nach auch passen. Da der socket nicht mer existiert,
>allerdings nachwievor als Empfänger registriert ist.
>
>MfG aus dem tiefsten Süden!
>Gerald

Viele Grüße aus dem Norden

Mario

Mario Schattschneider

unread,
Sep 22, 2004, 4:41:06 AM9/22/04
to
Jochen Theodorou schrieb:

Hallo Jochen,

Dann sollte es mit einem try und catch Block um diese Anweisung getan
sein oder?
>
>Gruss theo

Gruß

Mario

Jochen Theodorou

unread,
Sep 22, 2004, 5:36:02 AM9/22/04
to
Mario Schattschneider schrieb:

> Jochen Theodorou schrieb:
>
> Hallo Jochen,
>
>>Mario Schattschneider schrieb:
>>
>>[...]
>>
>>>Wenn ich versuche das Socket zu schließen erhalte ich folgende
>>>Fehlermeldung:
>>>java.net.SocketException: socket closed
[...]

>>>
>>>Die Zeile 67 enhält folgendes: socket.receive(packet);
>>
>>Das ist nachdem du den Socket geschlossen hast. Du kannst von einem
>>gechlossenen Socket nix empfangen also kommt eine Exception.
>
>
> Dann sollte es mit einem try und catch Block um diese Anweisung getan
> sein oder?

Jein. Diese Exception wird geworfen weil du einen logischen Fehler hast.
#die Exception wird geworfen weil es aus irgendwelchen Gründen nicht
möglich ist ein Paket zu empfangen. In deinem Fall sieht es so aus, als
wäre das niemals möglich denn

> public void setIPAddress(String address) {
> // ToDO Fehlerbehandlung
>
> MultiCastThread = null;
> if (MultiCastThread == null) {
> try {
> socket.leaveGroup(InetAddress.getByName(ipAddress));
> //Fehler
> socket.close();
> }
> catch (IOException ex) {
> ex.printStackTrace();
> System.out.println(ex.getMessage());
> }
> this.ipAddress = address;
> MultiCastThread = new Thread(this);
> MultiCastThread.start();
> }
> }

hiermit erzeugst du einen MulticastThread und

> while (MultiCastThread != null) {
> byte[] buf = new byte[2048];
> DatagramPacket packet = new DatagramPacket(buf, buf.length);
>
> socket.receive(packet);
> rb.put(packet);

und hiermit liest du, wenn dieser Thread !=null ist. Doch da zuvor ein
socket.close() kam, kann das receive nicht fuktionieren. Natürlich
kannst du da ein try-catch entsprechend drum herum packen, solltest du
sogar, aber der logische Fehler bleibt. Zudem hab ich da noch ein paar
Anmerkungen: Variablennamen startet man in Java eigentlich immer klein,
damit man sie von Klassen unterscheiden kann. Du kannst ja
MulticastThread einfach multicastingThread nennen. Ausserdem ist mir
nicht klar was der macht - du hast ja auch garnix dazu geschrieben...
Für das Empfangen von Paketen kann er kaum zuständig sein, da das ja die
zitierte while-Schleife macht.... oder doch? Oh ich sehe gerade ein
MultiCastThread = new Thread(this); Nein, sowas hab ich persönlich
garnicht gerne... die while-Schleife ist doch dafür zuständig... Warum
lagerst du das nicht in eine innere Klasse aus? Etwa so:

class MulticastHandler extends Thread{
booelan keepRunning = true;
InetAddress group;

MulticastHandler(String ip, int port) {
group = InetAddress.getByName(ip);
socket = new MulticastSocket(port);
socket.joinGroup(group);
}

public void run() {
while (keepRunning) {


DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
rb.put(packet);
}
}

public void stopHandler() {
keepRunning = false;
socket.leaveGroup(group);
socket.close();
}
}

kann man sicherlich um einiges Verbessern, aber im Prinzip könnte man
das so machen... achja...

> public void setIPAddress(String address) {
> multiCastThread = new MulticastHandler(address);
> multiCastThread.start();
> }
> }

Gruss theo

Mario Schattschneider

unread,
Sep 23, 2004, 6:07:57 AM9/23/04
to
Jochen Theodorou schrieb:

Zunächst einmal danke für die zahlreichen Tips.

>Mario Schattschneider schrieb:
>> Jochen Theodorou schrieb:

>>>[...]
>>>
>>>>Wenn ich versuche das Socket zu schließen erhalte ich folgende
>>>>Fehlermeldung:
>>>>java.net.SocketException: socket closed
>[...]
>>>>
>>>>Die Zeile 67 enhält folgendes: socket.receive(packet);
>>>
>>>Das ist nachdem du den Socket geschlossen hast. Du kannst von einem
>>>gechlossenen Socket nix empfangen also kommt eine Exception.
>>
>>
>> Dann sollte es mit einem try und catch Block um diese Anweisung getan
>> sein oder?
>
>Jein. Diese Exception wird geworfen weil du einen logischen Fehler hast.
>#die Exception wird geworfen weil es aus irgendwelchen Gründen nicht
>möglich ist ein Paket zu empfangen. In deinem Fall sieht es so aus, als
>wäre das niemals möglich denn

Doch eigentlich ist dies möglich, sobald die Klasse instanziert wird,
wird auch das Thread gestartet. Für die Multicastadresse wird dann
eine Defaultadresse genommen.

>
>> public void setIPAddress(String address) {
>> // ToDO Fehlerbehandlung
>>
>> MultiCastThread = null;
>> if (MultiCastThread == null) {
>> try {
>> socket.leaveGroup(InetAddress.getByName(ipAddress));
>> //Fehler
>> socket.close();
>> }
>> catch (IOException ex) {
>> ex.printStackTrace();
>> System.out.println(ex.getMessage());
>> }
>> this.ipAddress = address;
>> MultiCastThread = new Thread(this);
>> MultiCastThread.start();
>> }
>> }
>
>hiermit erzeugst du einen MulticastThread und
>
>> while (MultiCastThread != null) {
>> byte[] buf = new byte[2048];
>> DatagramPacket packet = new DatagramPacket(buf, buf.length);
>>
>> socket.receive(packet);
>> rb.put(packet);
>
>und hiermit liest du, wenn dieser Thread !=null ist. Doch da zuvor ein
>socket.close() kam, kann das receive nicht fuktionieren.

Das erscheint mir logisch, daß es nicht funktionieren kann wenn ich
den Socket vorher schließe. Aber wie stelle ich es an, daß der
Anwender zu einer anderen Multicastgruppe wechseln kann, auch wenn
bereits Daten in der alten Gruppe empfangen wurden?

Das Problem scheint doch die recieve Methode zu sein, die so lange
wartet bis ein Paket kommt oder?

>Natürlich
>kannst du da ein try-catch entsprechend drum herum packen, solltest du
>sogar, aber der logische Fehler bleibt. Zudem hab ich da noch ein paar
>Anmerkungen: Variablennamen startet man in Java eigentlich immer klein,
>damit man sie von Klassen unterscheiden kann. Du kannst ja
>MulticastThread einfach multicastingThread nennen.

Da hast Du natürlich Recht, warum ich die Variable groß geschrieben
habe ist mir selber nicht klar.

>Ausserdem ist mir
>nicht klar was der macht - du hast ja auch garnix dazu geschrieben...
>Für das Empfangen von Paketen kann er kaum zuständig sein, da das ja die
>zitierte while-Schleife macht.... oder doch? Oh ich sehe gerade ein
>MultiCastThread = new Thread(this); Nein, sowas hab ich persönlich
>garnicht gerne... die while-Schleife ist doch dafür zuständig... Warum
>lagerst du das nicht in eine innere Klasse aus? Etwa so:
>

Der Thread empfängt zum einen die Pakete und schreibt diese dann in
einen Ringpuffer. Der Zugriff auf diesen Ringpuffer soll durch
verschiedenen Threads geschehen (ein lesender und ein schreibender
Thread).


>class MulticastHandler extends Thread{
> booelan keepRunning = true;
> InetAddress group;
>
> MulticastHandler(String ip, int port) {
> group = InetAddress.getByName(ip);
> socket = new MulticastSocket(port);
> socket.joinGroup(group);
> }
>
> public void run() {
> while (keepRunning) {
> DatagramPacket packet = new DatagramPacket(buf, buf.length);
> socket.receive(packet);
> rb.put(packet);
> }
> }
>
> public void stopHandler() {
> keepRunning = false;
> socket.leaveGroup(group);
> socket.close();
> }
>}
>
>kann man sicherlich um einiges Verbessern, aber im Prinzip könnte man
>das so machen... achja...
>
> > public void setIPAddress(String address) {
> > multiCastThread = new MulticastHandler(address);
> > multiCastThread.start();
> > }
> > }
>
>Gruss theo

Gruß Mario

Jochen Theodorou

unread,
Sep 23, 2004, 11:34:52 AM9/23/04
to
Mario Schattschneider schrieb:
[...]

> Aber wie stelle ich es an, daß der
> Anwender zu einer anderen Multicastgruppe wechseln kann, auch wenn
> bereits Daten in der alten Gruppe empfangen wurden?
>
> Das Problem scheint doch die recieve Methode zu sein, die so lange
> wartet bis ein Paket kommt oder?

Ah, ok jetzt verstehe ich das Problem... Wenn du meine Lösung mit dem
Thread benutzt, dann ist das fast automatisch gelöst, denn du würdest
für jede Gruppe einen eigenen Thread starten. Der Socket sollte dann
halt eine lokale Varibale von MulticastHandler sein. zudem sollte man
die Schleife vielleicht ein wenig früher abbrechen, dann wird nix mehr
in den Puffer geschrieben wenn man etwas aus einer Grupee empfaängt, die
man eigentlich garnichtmehr belauschen will:

class MulticastHandler extends Thread{
booelan keepRunning = true;
InetAddress group;

MulticastSocket socket;

MulticastHandler(String ip, int port) {
group = InetAddress.getByName(ip);
socket = new MulticastSocket(port);
socket.joinGroup(group);
}

public void run() {
while (true) {


DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);

if (!keepRunning) break;
rb.put(packet);
}
}

public void stopHandler() {
keepRunning = false;
socket.leaveGroup(group);
socket.close();
}
}

jetzt wartet der Thread auf ein Packet und sobald er es empfängt und
nicht gestoppt wurde packt er das empfangene Packet in den Ringpuffer.

Möglicherweise gibt es auch eine Möglichkeit über NIO das blocking zu
verhindern.... aber da kenne ich mich nun überhaupt nicht aus.

Gruss theo

0 new messages