# UDP DatagrammSocket



## sup? (15. Nov 2011)

Hi, ich hab anscheinend n Problem bei der Erstellung eines DatagrammSockets. 

Diese Klasse kapselt die Datagram-Sockets und stellt eine etwas komfortablere Schnittstelle zur Verfuegung :


```
public class UdpSocket 
{
    private static Log log = LogFactory.getLog(UdpSocket.class);
    
    private DatagramSocket socket;
    private InetAddress remoteAddress;
    private int remotePort;
    
    // Anzahl Wiederholungen beim Empfangen eines UDP-Paketes
    private static int numberOfRetries = 3;
    
    /**
     * Konstruktor
     * @param port UDP-Port, der lokal fuer das Datagramm-Socket verwendet werden soll
     */
    public UdpSocket() throws SocketException {
        socket = new DatagramSocket(50000);
        try {
	    	log.debug("Groesse des Empfangspuffers des Datagram-Sockets: " + socket.getReceiveBufferSize() + " Byte");
	    	log.debug("Groesse des Sendepuffers des Datagram-Sockets: " + socket.getSendBufferSize() + " Byte");
	    } catch (SocketException e){
	    	log.debug("Socketfehler: " + e);
	    }
    }
...
```

Der Server: 

```
.....

public static void main (String args[]) throws SocketException
	    {
	    	PropertyConfigurator.configureAndWatch("log4j.server.properties", 60 * 1000);
	    	
	    	while (true) {
	    		
	    	   		try {
	    				UdpSocket socket = new UdpSocket();
	    				
	    				EchoPDU echo;
	   	    			echo = (EchoPDU) socket.receive(10);
	   	    			long startTime = System.nanoTime();
	   	    			connections.put(echo.getClientName(),socket);
	   	    			echo.setServerTime(System.nanoTime() - startTime);	
	   	    			socket.send(socket.getRemoteAddress(), 500000, echo);
	   	    			
	    			} catch (IOException e) {
	    				// TODO Auto-generated catch block
	    				e.printStackTrace();
	    			} 


	    	}	
	    }
```

Exception:


```
java.net.BindException: Address already in use: Cannot bind
	at java.net.DualStackPlainDatagramSocketImpl.socketBind(Native Method)
	at java.net.DualStackPlainDatagramSocketImpl.bind0(Unknown Source)
	at java.net.AbstractPlainDatagramSocketImpl.bind(Unknown Source)
	at java.net.DatagramSocket.bind(Unknown Source)
	at java.net.DatagramSocket.<init>(Unknown Source)
	at java.net.DatagramSocket.<init>(Unknown Source)
	at java.net.DatagramSocket.<init>(Unknown Source)
	at edu.hm.dako.EchoApplication.UDPSingleThreaded.UdpSocket.<init>(UdpSocket.java:57)    //er meckert ueber -> socket = new DatagramSocket(44432);
	at edu.hm.dako.EchoApplication.UDPSingleThreaded.UDPSingleThreadedEchoServer.main(UDPSingleThreadedEchoServer.java:66)
```

Hab verschiedenste Ports ausprobiert, merkert immer


----------



## SlaterB (15. Nov 2011)

die Exception kommt erst beim zweiten Schleifendurchlauf, richtig?
du kannst nicht mehrere Sockets auf denselben Port eröffnen,
close() entweder den ersten korrekt oder verwende ihn wieder


----------



## sup? (16. Nov 2011)

Danke, hat gefunzt.
Jetzt gibts n weiteres Prob: 

Bei echo = (EchoPDU) socket.receive(10); meckert er, immer wieder solange der Server läuft:

```
java.net.SocketTimeoutException: Receive timed out
	at java.net.DualStackPlainDatagramSocketImpl.socketReceiveOrPeekData(Native Method)
	at java.net.DualStackPlainDatagramSocketImpl.receive0(Unknown Source)
	at java.net.AbstractPlainDatagramSocketImpl.receive(Unknown Source)
	at java.net.DatagramSocket.receive(Unknown Source)
	at edu.hm.dako.EchoApplication.UDPSingleThreaded.UdpSocket.receive(UdpSocket.java:112)
	at edu.hm.dako.EchoApplication.UDPSingleThreaded.UDPSingleThreadedEchoServer.main(UDPSingleThreadedEchoServer.java:69)
```

Die aufgerufene Methode im UDP Socket sieht so aus: 


```
public Object receive(int timeout) throws IOException 
    {
    	// Maximale Wartezeit fuer Receive am Socket einstellen
    	
    	try {
    		socket.setSoTimeout(timeout);
    	}
    	catch (SocketException e) {
    		log.error("RECEIVE: " + "Fehler beim Einstellen der maximalen Wartezeit");
        	throw e;
    	}   
        
        byte[] bytes = new byte[65527];
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length);

        for (int i = 0; i < numberOfRetries; i++) {

        	try {
        		// Blockiert nur, bis Timeout abgelaufen ist
        		socket.receive(packet);
        		log.debug("RECEIVE: Empfangene Datenlaenge:  " + packet.getLength());
        		break;
        	}
        	catch (SocketTimeoutException e1) {
        		log.debug("RECEIVE: " + "Socket Timeout " + (i+1));
        		//System.out.println("RECEIVE: " + "Socket Timeout " + (i+1));
        		if (i == (numberOfRetries-1)) {
        			// Alle Versuche ausgereizt
        			log.debug("RECEIVE: Wartezeit von " + timeout + " ms abgelaufen");
        			throw e1;
        		}
        	}
        	catch (IOException e2) {
        		log.error("RECEIVE: " + "Fehler beim Empfangen einer PDU ueber UDP");
        		throw e2;
        	}
        }
```


----------



## SlaterB (16. Nov 2011)

du hast doch das timeout eingestellt, 
wenn keine Nachricht kommt und die Zeit abläuft, was erwartest du dann?

die Methode receive() könnte sicherlich normal fertig werden, dannn müsste man schauen wie über den packet-Inhalt der Timeout zu erkennen ist,
ich glaube aber hier fliegt eine Exception, eben genau die SocketTimeoutException 


> Signals that a timeout has occurred on a socket read or accept.


SocketTimeoutException (Java Platform SE 7 )

dass die Exception fliegt ist also ganz normal, 
wie du danach weiterarbeitest ist vollkommen dir überlassen, du musst das ja nicht als Exception loggen


----------



## sup? (16. Nov 2011)

Vielen Dank! War mir da unsicher, da die Methode ja eigentlich nach 3 Fehlversuchen "RECEIVE: Wartezeit von " + timeout + " ms abgelaufen" ausgegeben werden sollte. Hab die UDP Socket Klasse selber nicht geschrieben, von daher fällt es mir grad schwer herauszufinden, wie der Recieve Prozees genau funzt.


----------

