UDPSocket

Hallo liebe Leute,

ich habe ein Problem mit dem ich einfach nicht voran komme. Ich arbeite mit Eclipse und möchte die unten aufgeführten Code ausführen.

1.) Ich bekomme es irgendwie nicht hin, eine Verbindung zwischen dem Client und den Server herzustellen.
2.) Nachdem Punkt 1.) scheitert, wird dann bei weiteren Versuchen immer diese Exception ausgelöst:

Code:
java.net.BindException: Address already in use: Cannot bind\n
=>closing datagram socket

PS.: Diesen Code habe ich von einem Buch "Parallele und Verteilte Anwendungen" abgeschrieben... Ich würde mich freuen, wenn Ihr mir in dieser Angelegenheit hilft, vielen Dank im Voraus

Server Code:
Java:
 package Kapitel_05;

public class Server {

	public static void main(String[] args) {
		
		int counter = 0;
		UDPSocket udpSocket = null;
		
		
		try{
					// create socket
			udpSocket = new UDPSocket(1250);
					// wait for request packets
			System.out.println("waiting for client requests");
					// execute client requests
			
			while(true){
					// receive request
				String request = udpSocket.receive(20);
					// perform increment operation
		
				if(request.equals("increment")){
					// perform increment
					counter++;
				}
				else if(request.equals("reset")){
					// perform reset
					counter = 0;
					System.out.println("counter reset by "+ udpSocket.getSenderAddress()+ ":"+ udpSocket.getSenderPort());
				}
		
				// generate answer
				String answer = String.valueOf(counter);
				// send answer
				udpSocket.reply(answer);
			}//while closing
		}
		catch(Exception e){
			System.out.println(e);
			System.out.println("=> closing datagram socket");
		
			if(udpSocket != null){
				udpSocket.close();

			}
		}
	}
}

Client Code:
Java:
package Kapitel_05;

import java.net.InetAddress;

public class Client{
	private static final int TIMEOUT = 10000; // 10 seconds

		public static void main(String args[]){
		
				if(args.length != 2){
					System.out.println("Notwendige Kommandozeilenargumente: "+ "<Name des Server-Rechners> <Anzahl>");
					return;
				}
				
		UDPSocket udpSocket = null;

		try{
			// create datagram socket
			udpSocket = new UDPSocket();
			udpSocket.setTimeout(TIMEOUT);
			// get inet addr of server

			InetAddress serverAddr = InetAddress.getByName(args[0]);
			// set counter to zero
			System.out.println("Zähler wird auf 0 gesetzt.");
			udpSocket.send("reset", serverAddr, 1250);
			String reply = null;
			
			// receive reply
				try{
					reply = udpSocket.receive(20);
					System.out.println("Zähler: " + reply);
				}
				catch(Exception e){
					System.out.println(e);
				}

				// get count, initialize start time
				System.out.println("Nun wird der Zähler erhöht.");
				int count = new Integer(args[1]).intValue();

				long startTime = System.currentTimeMillis();

				// perform increment "count" number of times

				for(int i = 0; i < count; i++){
					udpSocket.send("increment", serverAddr, 1250);

						try{
							reply = udpSocket.receive(20);
						}
						catch(Exception e){
							System.out.println(e);
						}
				}//end for loop

				// display statistics

				long stopTime = System.currentTimeMillis();
				long duration = stopTime - startTime;

				System.out.println("Gesamtzeit = " + duration + " msecs");

				if(count > 0){
					System.out.println("Durchschnittszeit = "+ ((duration) / (float) count)+ " msecs");
				}
				
				System.out.println("Letzter Zählerstand: " + reply);
		}catch(Exception e){
			
			System.out.println(e);
			System.out.println("=> DatagramSocket wird geschlossen");
		}
		
		if(udpSocket != null){
			udpSocket.close();
		}
}
}


UDPSocket:
Java:
package Kapitel_05;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;



/*
 *  Ferner merkt sich ein Objekt der Klasse
	UDPSocket die IP-Adresse und Portnummer 
	des zuletzt empfangenen DatagramPackets*/

public class UDPSocket {
												//Ein Objekt der Klasse DatagramSocket enthält neben den Daten die IP-Adresse und Portnummer des Partners
	protected DatagramSocket socket;			//Die Klassen DatagramSocket ebenso DatagramPacket werden benötigt zur Kommunikation über UDP
	private InetAddress address;				//Die Klasse InetAddress repräsentiert den Namen eines Rechners sowie die zugehörige IP-Adresse
	private int port;							//
	
	
	protected UDPSocket(DatagramSocket socket) { 
		this.socket = socket;
	}
	
	public UDPSocket() throws SocketException {
		this(new DatagramSocket());				//Parameterloser Konstruktor der Klasse DatagramSocket, wird im Moment nicht benutzte Portnummer(>=1024)
												//an den Socket (Steckdose) gebunden... Dieser Konstruktor wird in der Regel von clients verwendet
	}
	
	//int-argument wird die Portnummer, 
	//die  an den  neuen Socket gebunden werden soll
	//dieser Konstruktor wird in der Regel von server genutzt
	public UDPSocket(int port) throws SocketException {	
		this(new DatagramSocket(port));
	} 
	
	
	//Mit send ein DatagramPacket - Objekt gesendet
	//Zum senden der Daten, wird der Datentyp byte genutzt
	public void send(String s, InetAddress rcvrAddress, int rcvrPort) throws IOException{
		byte[] outBuffer = s.getBytes();
		DatagramPacket outPacket = new DatagramPacket(outBuffer, outBuffer.length, rcvrAddress,rcvrPort);
		this.socket.send(outPacket);
	} 
	
	//Mit receive wird ein DatagramPacket - Objekt abgefangen/erhalten/...
	//Die Methode ist blockierend, d.h.wenn in moment kein DatagramPacket - Objekt vorliegt, wird so lange gewartet, bis 
	//ein Paket eintrifft. Die Wartezeit kann durch einen dem receive vorausgehenden Aufruf von setSoTimeout befristet werden
	//Die aktuell eingestellte Frist kann mit getSoTimeout gelesen werden
	//Als Daten werden byte empfangen und in String gecastet
	public String receive(int maxBytes) throws IOException {
		byte[] inBuffer = new byte[maxBytes];
		DatagramPacket inPacket = new DatagramPacket(inBuffer, inBuffer.length);
		this.socket.receive(inPacket);
		this.address = inPacket.getAddress();
		this.port = inPacket.getPort();
		
		return new String(inBuffer,0,inPacket.getLength());
	}
	
	//mit der Methode reply kann OHNE angabe eines empfängers demjenigen geantwortet werden,
	//von dem zuletzt eine Nachricht empfangen wurde, 
	//indem die gemerkten Angaben verwendet werden
	//Diese gemerkten Angaben können durch Get-Methoden auch erfragt werden
	public void reply(String s) throws IOException {
		if(this.address == null) {
			throw new IOException("no one reply :(");
		}
		send(s,this.address,this.port);
	}
	
	//Die Klasse InetAddress stellt einen Rechnernamen und die dazugehörige IP-Adresse dar. 
	//MIt getHostName kann der Rechnername und mit getHostAddress die IP-Adresse gelesen werden
	//diese Methode liefert ein Objekt der Klasse InetAddress
	public InetAddress getSenderAddress() {
		return this.address;
	}
	
	//liefert die Portnummer des Servers/Senders
	public int getSenderPort() {
		return this.port;
	}
	
	//setzt die Zeit für die Wartezeit der Methode --> receive
	public void setTimeout(int timeout) throws SocketException {
		this.socket.setSoTimeout(timeout);
	}
	
	//Der Socket wird geschlossen
	//unter des Aufrufenden Objektes ist keine Kommunikation mehr möglich
	public void close() {
		this.socket.close();
	}
}
 
Zuletzt bearbeitet:

baba27

Mitglied
Ich bin per Zufall auf das gleiche Problem gestossen und konnte es zumindest zum Teil lösen. Man kann ein Flag setzen, dass man den Port nicht allein haben will. Wenn ein anderes Programm den Port auch nicht allein haben will, können scheinbar mehrere Programme auf den gleichen Port hören. Meine momentane Lösung:

Java:
DatagramSocket socket = new DatagramSocket(null);
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress("0.0.0.0",port));

Die Java-Applikation verbindet sich auch mit dem Port, aber hört seltsamerweise nur auf IPv6-Adressen. Ich weiss leider nicht, wie man dies dem Java sagen soll. Meiner Meinung nach ist die Adresse 0.0.0.0 eine IPv4 Adresse, weshalb ich eigentlich erwarten würde, dass auf IPv4 gehört wird. Meine Daten kommen aber leider über IPv4.
 

Neue Themen


Oben