DatagramSocket unter Debian (Linux)

mccae

Senfdazugeber
Grüße!

Leider habe ich folgendes Problem und ich weiß auch nicht ob das java oder linux-spezifisch ist:

Wenn ich einen DatagramSocket erstelle (dabei ist es egal ob ich den parameterlosen konstruktor benutze, oder auf InetAddress und port binde, oder auf eine InetSocketAddress).

Es ist auch egal ob ich auf die Adresse "127.0.0.1", "localhost", "0.0.0.0", oder auf die IP über die der Server aus dem Internet erreichbar ist binde.

Folgendes:

Ich möchte ein Datagrampacket schicken (an localhost, habe es aber auch mit Adressen aus dem Internet probiert).

Ich bekomme jedoch keine Antwort (timeout).

Das komische: Unter Windows funktioniert alles perfekt egal ob ich einen lokalen oder einen gameserver im internet ansteuere.

Auf meinem Linux Server (Debian 5.0 lenny) klappt das ganze jedoch nicht.
Die entsprechenden Ports sind freigegeben,...

Hier mal mein Code:

Java:
package at.co.lipski.twcc.network;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;

import at.co.lipski.twcc.logic.Time;

public class TWServerQuery {
	private int timeout;
	private int port;
	private DatagramSocket socko;
	
	public TWServerQuery(){
		port = 8303;
		timeout = 5000;
	}
	
	public TWServerQuery(int port, int timeout, DatagramSocket socko){
		
		if(port>1024){
			this.port = port;
		}
		else{
			this.port = 8303;
		}
		
		if(timeout > 0){
			this.timeout = timeout;
		}
		else{
			this.timeout = 5000;
		}
		this.socko = socko;
	}
	
	public synchronized TeeWorldsStatus doQuery(){
		TeeWorldsStatus s = null;
		try{
			socko.setSoTimeout(timeout);
			byte[] sendData; 
			byte[] receiveData = new byte[1024];      
			String sentence = "ÿÿÿÿÿÿÿÿÿÿgief";
			sendData = sentence.getBytes();
			
			DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("127.0.0.1"), port);
			
			System.out.println("Sending packet: "+sendPacket.getAddress().toString()+" "+sendPacket.getPort()+" "+sendPacket.getLength());
			socko.send(sendPacket);
			System.out.println("Packet sent!");
			
			DatagramPacket receivePacket = new DatagramPacket(receiveData, 1024);
			
			System.out.println("Receiving,...");
			socko.receive(receivePacket);      
			String modifiedSentence = new String(receivePacket.getData());      
			int index = modifiedSentence.indexOf("info")+4;
			
			String [] infos = modifiedSentence.substring(index).split(""+(char)0);
			 
			String version = infos[0];
			String serverName= infos[1];
			String map = infos[2];
			String gametype = infos[3];
			String percentDone = infos[5];
			String numPlayers = infos[6];
			String maxplayers = infos[7];
			
			ArrayList<String[]> l = new ArrayList<String[]>();
			
			if(infos.length>7){
				for(int i = 8;i<infos.length;i+=2){
			        String [] array = new String[2];
					array[0] = infos[i];
					array[1] = infos[i+1];
					l.add(array);
				}
			}
			 
			s = new TeeWorldsStatus();
			 
			s.setVersion(version);
			s.setServerName(serverName);
			s.setMap(map);
			s.setGametype(gametype);
			s.setPercentDone(percentDone);
			s.setNumPlayers(numPlayers);
			s.setMaxplayers(maxplayers);
			s.setPlayers(l);
		}
		
		catch (Exception e){
			boolean truetrue = false;
			boolean isbound = false;
			String addr = "";
			if(socko==null){
				truetrue = true;
			}
			else{
				isbound = socko.isBound();
				addr = ""+socko.getLocalAddress()+socko.getLocalPort();
			}
			System.out.println(Time.genTimeStamp()+"Internal error: "+e.getMessage()+
					"\n\nIs DatagramSocket null? "+truetrue+"\nIs bound: "+isbound+"\n"+addr+"\n");
			e.printStackTrace();
		}
		return s;
	}
}

Nochmal ganz kurz zur Erklärung:

TeeWorlds ist ein 2D Cartoonshooter.

Der obige Code soll den Status eines TeeWorlds - servers erfahren der auf 127.0.0.1 läuft. Ich habe es aber auch mit anderen Servern im Internet probiert.

Unter Windows funktioniert alles ohne Probleme, nur unter Linux kann anscheinend weder unter localhost pakete empfangen, noch welche die von außerhalb kommen,...

Auf wenn ich probeweise die Firewall ausschalte und alle Ports öffne (ich weiß, böse!) bekomme ich keine Antwort,...

Entweder landet das gesendete Paket im Nirvana oder ich kann einfach keine Empfangen,...

Kann mir jemand weiterhelfen?
 
Bist du dir sicher, dass die Ports freigegeben sind? Bei Linux reicht das nicht, dass du die Ports im Router umleitest. Die meisten Linux-Systeme haben die Angewohnheit alle Ports zu schließen und geben sie erst frei, wenn nach Außen eine Verbindung aufgebaut wird. Das ist auch schön, nur stellst du in deinem Fall keine Verbindung nach Außen her, weil UDP im Gegensatz zu TCP verbindungslos arbeitet. Oder anders gesagt: Du jagst ein Packet raus und es ist dem Sender vollkommen egal, ob es auch ankommt. Folglich erwartet der Sender auch keine Antwort und deswegen wird der entsprechende Port auch nicht aufgemacht.
 
Bist du dir sicher, dass die Ports freigegeben sind? Bei Linux reicht das nicht, dass du die Ports im Router umleitest. Die meisten Linux-Systeme haben die Angewohnheit alle Ports zu schließen und geben sie erst frei, wenn nach Außen eine Verbindung aufgebaut wird. Das ist auch schön, nur stellst du in deinem Fall keine Verbindung nach Außen her, weil UDP im Gegensatz zu TCP verbindungslos arbeitet. Oder anders gesagt: Du jagst ein Packet raus und es ist dem Sender vollkommen egal, ob es auch ankommt. Folglich erwartet der Sender auch keine Antwort und deswegen wird der entsprechende Port auch nicht aufgemacht.

Die Ports sind frei, und nicht Java-Programme haben auch keine Probleme mit UDP,...

Mit "Ports freigegeben" habe ich ja unter anderem die iptables gemeint
 
Zuletzt bearbeitet:
Hallo,

Könnte es vielleicht daran liegen?
DatagramPacket receivePacket = new DatagramPacket(receiveData, 1024);
(Bzw. daran das ich Windows / Linux unterschiedlich Verhalten... )
Was passiert denn wenn du
Java:
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
verwendest?


folgendes funktioniert bei mir unter Ubuntu Linux 9.04 als normaler User einwandfrei :
Java:
package de.tutorials;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class UPDClientServerExample {

    final static int port = 4711;

    /**
     * @param args
     */
    public static void main(String[] args) {
        
        ExecutorService
         executorService = Executors.newCachedThreadPool();
        
        executorService.execute(new Runnable() {
            public void run() {
                try {
                    DatagramSocket socket = new DatagramSocket(port);

                    byte[] data = new byte[13];
                    while (true) {
                        DatagramPacket packet = new DatagramPacket(data,
                                data.length);
                        socket.receive(packet);

                        ByteBuffer buffer = ByteBuffer.wrap(data);
    
                        
                        int sequence = buffer.getInt();
                        byte action = buffer.get();
                        long timestamp = buffer.getLong();
                        
                        System.out.println(Thread.currentThread()
                                + " received: S:" + sequence + " A:" + action + " T:" + new Date(timestamp));
                        
                        if(action == (byte)-1){
                            break;
                        }
                    }
                    
                    socket.close();

                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        });

        executorService.execute(new Runnable() {
            public void run() {
                try {
                    DatagramSocket socket = new DatagramSocket();

                    for  (int i = 0; i<= 10;i++) {
                        DatagramPacket packet = createPacket(i, i == 10 ? (byte)-1 : (byte)0);
                        System.out.println(Thread.currentThread()
                                + " sending: " + packet);
                        socket.send(packet);
                        TimeUnit.SECONDS.sleep(1);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        
        executorService.shutdown();

    }

    private static DatagramPacket createPacket(int sequence, byte command) throws Exception {
        
        //payload = 4 bytes sequence, 1 byte command,  8 bytes timestamp
        
        byte[] payload = new byte[13];
        ByteBuffer buffer = ByteBuffer.wrap(payload);
        
        buffer.putInt(sequence);
        buffer.put(command);
        buffer.putLong(System.currentTimeMillis());
        
        DatagramPacket packet = new DatagramPacket(payload, payload.length,    InetAddress.getLocalHost(), port);
        return packet;
    }

}

Ausgabe:
Code:
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@39d99a4d
Thread[pool-1-thread-1,5,main] received: S:0 A:0 T:Thu Jul 16 20:13:45 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@9e97676
Thread[pool-1-thread-1,5,main] received: S:1 A:0 T:Thu Jul 16 20:13:46 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@3e60420f
Thread[pool-1-thread-1,5,main] received: S:2 A:0 T:Thu Jul 16 20:13:47 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@219106c7
Thread[pool-1-thread-1,5,main] received: S:3 A:0 T:Thu Jul 16 20:13:48 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@13d4c61c
Thread[pool-1-thread-1,5,main] received: S:4 A:0 T:Thu Jul 16 20:13:49 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@761a626f
Thread[pool-1-thread-1,5,main] received: S:5 A:0 T:Thu Jul 16 20:13:50 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@3e34a1fc
Thread[pool-1-thread-1,5,main] received: S:6 A:0 T:Thu Jul 16 20:13:51 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@7176c74b
Thread[pool-1-thread-1,5,main] received: S:7 A:0 T:Thu Jul 16 20:13:52 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@2d16471f
Thread[pool-1-thread-1,5,main] received: S:8 A:0 T:Thu Jul 16 20:13:53 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@11975b59
Thread[pool-1-thread-1,5,main] received: S:9 A:0 T:Thu Jul 16 20:13:54 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@67ee3914
Thread[pool-1-thread-1,5,main] received: S:10 A:-1 T:Thu Jul 16 20:13:55 CEST 2009

Gruß Tom
 
Hallo,

Könnte es vielleicht daran liegen?

(Bzw. daran das ich Windows / Linux unterschiedlich Verhalten... )
Was passiert denn wenn du
Java:
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
verwendest?

Leider passiert gar nichts,...

Ich weiß ja, dass receiveData eine Länge von 1024 hat. Weshalb sollte ich receiveData.length verwenden?

Das ganze ist total myteriös,...
 
Hallo,

Ich weiß ja, dass receiveData eine Länge von 1024 hat. Weshalb sollte ich receiveData.length verwenden?
Okay hatte ich übersehen. Trotzdem wenn du die größe von receiveData Änderst musst du die andere Stelle auch immer mitanpassen... insofern ist receiveData.length schon besser.

Funktioniert mein kleines UDP Beispiel?

Bekommst du ne Exception oder bleibt das Ganze einfach nur Hängen? Mach mal einen ThreadDump.
Unter Linux kannst du via Ctrl + \ gleichzeitig in der Konsole einen ThreadDump erzeugen lassen.

Eine andere Möglichkeit wäre ein kill -QUIT an den entsprechenden JVM Prozess zu senden.

Wenn du den hast kannst du genau sehen wo der Thread innerhalb von receive... wartet und damit eventuell
Rückschlüsse auf die Fehlerursache ziehen.

Gruß Tom
 
Hallo,


Okay hatte ich übersehen. Trotzdem wenn du die größe von receiveData Änderst musst du die andere Stelle auch immer mitanpassen... insofern ist receiveData.length schon besser.

Funktioniert mein kleines UDP Beispiel?

Bekommst du ne Exception oder bleibt das Ganze einfach nur Hängen? Mach mal einen ThreadDump.
Unter Linux kannst du via Ctrl + \ gleichzeitig in der Konsole einen ThreadDump erzeugen lassen.

Eine andere Möglichkeit wäre ein kill -QUIT an den entsprechenden JVM Prozess zu senden.

Wenn du den hast kannst du genau sehen wo der Thread innerhalb von receive... wartet und damit eventuell
Rückschlüsse auf die Fehlerursache ziehen.

Gruß Tom

Hm,...
Das ganze scheint zu funktionieren,...

Hier der Output:

Code:
vadmin55:~# java -jar test.jar
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@156ee8e
Thread[pool-1-thread-1,5,main] received: S:0 A:0 T:Fri Jul 17 16:40:43 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@e0e1c6
Thread[pool-1-thread-1,5,main] received: S:1 A:0 T:Fri Jul 17 16:40:44 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@6ca1c
Thread[pool-1-thread-1,5,main] received: S:2 A:0 T:Fri Jul 17 16:40:45 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@1bf216a
Thread[pool-1-thread-1,5,main] received: S:3 A:0 T:Fri Jul 17 16:40:46 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@12ac982
Thread[pool-1-thread-1,5,main] received: S:4 A:0 T:Fri Jul 17 16:40:47 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@c20e24
Thread[pool-1-thread-1,5,main] received: S:5 A:0 T:Fri Jul 17 16:40:48 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@2e7263
Thread[pool-1-thread-1,5,main] received: S:6 A:0 T:Fri Jul 17 16:40:49 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@157f0dc
Thread[pool-1-thread-1,5,main] received: S:7 A:0 T:Fri Jul 17 16:40:50 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@863399
Thread[pool-1-thread-1,5,main] received: S:8 A:0 T:Fri Jul 17 16:40:51 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@a59698
Thread[pool-1-thread-1,5,main] received: S:9 A:0 T:Fri Jul 17 16:40:52 CEST 2009
Thread[pool-1-thread-2,5,main] sending: java.net.DatagramPacket@141d683
Thread[pool-1-thread-1,5,main] received: S:10 A:-1 T:Fri Jul 17 16:40:53 CEST 2009


Also wird es wohl ein Problem mit der Linux-version des Programms sein, welches antworten soll,...
 
Zuletzt bearbeitet:
Bitte entschuldigt, dass ich meinen Thread wieder aus der Versenkung hole, aber ich glaube jetzt den Grund der Fehlfunktion gefunden zu haben....

Wer den Thread gelesen hat, weiss, dass ich ein UDP paket an ein lokales tool schicke und dieses nicht antwortet (aber nur unter Linux).

Vor kurzem habe ich herausgefunden, dass Linux Maschinen einen anderen Zeichensatz benutzen.
Der Inhalt des UDP-pakets ist hardcoded und ist "ÿÿÿÿÿÿÿÿÿÿgief".

Mein Linux Server benutzt den Zeichensatz: US-ASCII, und meine Windows Maschine den Windows Latin 1 Zeichensatz.

Mir ist aufgefallen dass das Zeichen 'ÿ' nicht im US-ASCII Satz vorkommt.
Liegt es möglicherweise daran?

Werden gehardcodete Zeichen mit dem Zeichensatz des lokalen Systems encoded?

Wenn ja, gibt es eine Möglichkeit das default-Charset während der Laufzeit zu definieren?
 

Neue Beiträge

Zurück