Suche nach Servern - Antworten cachen

Unicate

Erfahrenes Mitglied
Hallo alle zusammen!

Ich habe einen Client geschrieben, der nach Servern im lokalen Netz suchen soll. Also schickt der Client eine Anfrage an die Broadcastadresse der Netzwerkkarte.(Quasi an alle im lokalen Netzwerk befindlichen Rechner).

Wie fang ich die auf ohne Probleme mit der synchronität zu bekommen? Also wenn da 10 Server sind antworten die ja auch zu fast der gleichen Zeit. Wie kann ich das vernünftig handlen?

Kann ich den datainputstream irgendwie synchronizen?
 
Zuletzt bearbeitet:
Hallo,
hast du es denn schonmal versucht einfach so zu programmieren? Wenn das bearbeiten der Antwortpakete kein großer aufwand ist, dann sollte das auch ohne spezielle Server gehen denke ich, da ein Netzwerk ein serielles System ist und somit die Rechner, welche die Antwort schicken sollen, dies auch nur nacheinander tun können. Da das ganze bei der heutigen Technik nur ein paar Milisekunden oder weniger dauert kommt es einem nur so vor, als ob es gleichzeitig geschieht. Man muss sich aber immer vor Auge halten, wie ein PC überhaupt tickt und in welcher Geschwindigkeit er das tut. die meisten Operationen, dauern nicht mal eine Milisekude.

Edit:

Du könntest alternativ vielleicht die empfangenen Datenpakete in einer ArrayList spreichern und diese erst durcharbeiten, wenn du über das Netzwerk für eine bestimmte Zeit keine Pakete mehr erhälst. Möglich währe das durch die setSoTimeout(timeout) methode. Wenn die Zeit abläuft wird eine Exception geworfen, durch die du dann eine Funktion zum Abarbeiten der Daten aufrufen kannst. Dadurch sollte es ohne großen Aufwand auf jeden Fall funktionieren

Edit 2:
Hier ein Beispiel, wie ich mir es vorgestellt habe:

Java:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;


public class Foo {
	public static final int PORT = 1234;
	public static final int TIMEOUT = 500;
	public static final int BUFFER_SIZE = 10*1024;
	
	public static void main(String[] args) throws IOException {
		ArrayList<DatagramPacket> cachedPackets = new ArrayList<DatagramPacket>();
		
		DatagramSocket socket = new DatagramSocket(PORT);
		socket.setSoTimeout(TIMEOUT);
		
		try {
			while(true) {
				DatagramPacket packet = new DatagramPacket(new byte[BUFFER_SIZE], 0, BUFFER_SIZE);
				socket.receive(packet);
				cachedPackets.add(packet);
			}
		} catch (SocketTimeoutException e) {
			handleReceivedPackets(cachedPackets);
		}
	}

	private static void handleReceivedPackets(
			ArrayList<DatagramPacket> cachedPackets) {
		// Daten verarbeiten
	}

}
 
Zuletzt bearbeitet:
Hallo,
hast du es denn schonmal versucht einfach so zu programmieren? Wenn das bearbeiten der Antwortpakete kein großer aufwand ist, dann sollte das auch ohne spezielle Server gehen denke ich, da ein Netzwerk ein serielles System ist und somit die Rechner, welche die Antwort schicken sollen, dies auch nur nacheinander tun können. Da das ganze bei der heutigen Technik nur ein paar Milisekunden oder weniger dauert kommt es einem nur so vor, als ob es gleichzeitig geschieht. Man muss sich aber immer vor Auge halten, wie ein PC überhaupt tickt und in welcher Geschwindigkeit er das tut. die meisten Operationen, dauern nicht mal eine Milisekude.

Edit:

Du könntest alternativ vielleicht die empfangenen Datenpakete in einer ArrayList spreichern und diese erst durcharbeiten, wenn du über das Netzwerk für eine bestimmte Zeit keine Pakete mehr erhälst. Möglich währe das durch die setSoTimeout(timeout) methode. Wenn die Zeit abläuft wird eine Exception geworfen, durch die du dann eine Funktion zum Abarbeiten der Daten aufrufen kannst. Dadurch sollte es ohne großen Aufwand auf jeden Fall funktionieren

Edit 2:
Hier ein Beispiel, wie ich mir es vorgestellt habe:

Java:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;


public class Foo {
	public static final int PORT = 1234;
	public static final int TIMEOUT = 500;
	public static final int BUFFER_SIZE = 10*1024;
	
	public static void main(String[] args) throws IOException {
		ArrayList<DatagramPacket> cachedPackets = new ArrayList<DatagramPacket>();
		
		DatagramSocket socket = new DatagramSocket(PORT);
		socket.setSoTimeout(TIMEOUT);
		
		try {
			while(true) {
				DatagramPacket packet = new DatagramPacket(new byte[BUFFER_SIZE], 0, BUFFER_SIZE);
				socket.receive(packet);
				cachedPackets.add(packet);
			}
		} catch (SocketTimeoutException e) {
			handleReceivedPackets(cachedPackets);
		}
	}

	private static void handleReceivedPackets(
			ArrayList<DatagramPacket> cachedPackets) {
		// Daten verarbeiten
	}

}

Sorry, das ist Blödsinn. Parallel viele Requests gleichzeitig bearbeiten ist kein Problem. Schon mal übelregt wie Webserver usw arbeiten? Dazu braucht man non-blocking sockets. "Blocking" heißt das der Server solange wie er garde einen Request bearbeitet nichts anderes macht, non-blocking heißt der Server nimmt einen Request an und deligiert ihn per Dispatcher an einen thread der die Abarbeitung macht. (Zumindest wird das zumeist so implementiert)

Du hast in sofern recht das die Pakete sequentiell bei dem Server ankommen - mehr aber auch nicht. Nur das reine Connection aktzeptieren is seriell solange du mit nur einem Port arbeitest, das Processing usw kann man parallelisieren.

Ich schlage vor einfach mal einen Blick in das PDF zu werfen das ich verlinkt habe, oder alternativ die libs Netty oder MINA anzusehen.
 
Ja Webserver arbeiten ja auch mit dem TCP Protokoll und durch die Sockets ist das Bearbeiten einzelner Socket-Verbindungen per Thread kein Problem -> Socket an einen neuen Thread übergeben

Allerdings gibt es im UDP Protokoll keine Sockets, die man einfach an einen Thread übergeben kann. (Jeden falls kenn ich bisher keine. Habe mich mit UDP aber auch nocht nicht so sehr auseinander gesetzt)
Bei einen DatagramSocket werden alle Datenpakete, soweit ich es kenne, über den gleichen Socket verschickt nicht so wie in einem TCP Programm.

Falls es so ist, wie ich annehme, dann könnte man aber Threads erstellen, denen eine IP zugeordet werden. Gibt es noch keinen Thread, der für die IP eines Paketes zuständig ist, erstellt man einen neuen und weist ihm diese zu. Die IPs der reinkommenden Pakete werden dann mit den IPs der Threads verglichen und dann dem passenden Thread übergeben.

Habe momentan kein PDF Reader aufm PC und kann mir daher nicht angucken, ob es sich in deiner PDF rein um TCP Verbindungen handelt oder nicht.
Wenn es jedoch eine Möglichkeit gibt mit UDP Verbindungen ähnlich zu arbeiten wie mit den Sockets einer TCP Verbindung, dann würde mich das gerne interessieren. Eventuell mit Beispielcode :)

Edit
Sorry. Für mich hatte sich das Problem zu erst irgendwie nach einem UDP basierendem Netzwerk angehört. Aber lese gerade vom Synchronisieren eines DataInputStreams wodurch es sich ja nun um ein TCP Netzwerk handelt.
 
Zuletzt bearbeitet:
Hiho. Hier mal als Ergänzung ein simpler Server, der jede Verbindung in einem eigenen Thread bearbeitet:

Java:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;


public class Foo {
	public static final int PORT = 1234;
	
	public static void main(String[] args) {
		try {
			// ServerSocket erstellen
			ServerSocket serverSocket = new ServerSocket(PORT);
			
			while(true) {
				// Eingehende Verbindungsanfragen annehmen
				Socket newConnection = serverSocket.accept();
				
				// Neue Verbindung an einen neuen Thread übergeben, der diese bearbeitet
				new ConnectionHandler(newConnection);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Java:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;


public class ConnectionHandler implements Runnable {
	private Socket mySocket;
	private InputStream in;
	private OutputStream out;
	
	public ConnectionHandler(Socket socket) {
		mySocket = socket;

		// Neuen Thread starten
		new Thread(this).start();	
	}

	@Override
	public void run() {
		// Hier findet die Kommunikation und Bearbeitung statt
		try {
			in = mySocket.getInputStream();
			out = mySocket.getOutputStream();
			
			// Einfacher Echoserver
			String inputData = readLine();
			writeLine(inputData);
			
			// Verbindung beenden
			disconnect();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void disconnect() {
		try {in.close();} catch (Exception e){}
		try {out.close();} catch (Exception e){}
		try {mySocket.close();} catch (Exception e){}
	}
	
	public String readLine() throws IOException {
		return new BufferedReader(new InputStreamReader(in)).readLine();
	}
	
	public void writeLine(String data) throws IOException {
		BufferedWriter bOut = new BufferedWriter(new OutputStreamWriter(out));
		bOut.write(data + "\n");
		bOut.flush();
	}
}
 
Zuletzt bearbeitet:
@d4rkY89

[...] da ein Netzwerk ein serielles System ist [...]

so ein totaler schwachsinn ...

du hast wohl noch n TokenRing oder n ThikNet ...
heutige Fast-Ethernet arbeiten im FullDuplex ... und das sogar PARALLEL
ein netzwerk an sich ist nur dur seine normalerweise stern-topologie noch lange kein serieles system ...
für die einzelne verbindung eines endgerätes zum nächsten hub / switch / router / backbone / etc mag das halbwegs zu treffen ...
da kommt es aber immer auf die hardware-implementierung an ...
in meinem netz ist die gesamte hardware so ausgelegt das "quasi"-gleichzeitig 2 oder mehr ethernet-frames über die leitung geschoben werden können ... das das trotzdem nur seriel passiert da auf nem kabel nunmal nur 1 oder 0 liegen können ist schon physikalisch begründet ...

um jetzt aber mal auf das GESAMTE netz zu kommen ... stell dir vor du hast n router an dem 4 pc's angeschlossen sind und der n up-link zur nächst höheren instanz hat ...
and kann das ganze trotzdem parallel ablaufen wenn z.b. pc 2 idle is ... pc 1 mit pc 4 daten austauscht und pc 3 mittem uplink ... da is nix seriel ...
selbst die meisten home-geräte sind so aufgebaut das meist mehrere stacks gleichzeitig bearbeitet werden können ohne den anderen in die quere zu kommen ...

ich möchte wirklich mal *abgesehen von den alten Ring-netzen* n beispiel eines modernen 1GBit/s netzwerkes haben welches SERIEL arbeitet ...
so viel mal zu deiner behauptung das netzwerke grundsätzlich serielle anlagen wären
 
Okay. Kein Grund gleich angreiflich zu werden. Jedenfalls könnte man "das ist totaler schwachsin" etwas freundlicher ausdrücken und mal drüber nachdenken, ob sich nicht jemand etwas doof ausgedrückt haben könnte, was mir ziemlich oft passiert, wenn mir gerade viel durch den Kopf geht. Wenn ein Netzwerk sieriell wäre, dann würden wir jetzt noch halb in der Steinzeit leben :D

Jedoch heißt FullDuplex auch nicht gleich paralleles Kommunizieren, also gleichzeitig mit 3 Rechnern Daten austauschen, was man in deinem Fall vielleicht auch missverstehn könnte. Es bedeuted lediglich, dass eine Netzwerkkarte in der Lage ist gleichzeitig Daten über Kanal A zu schicken, während sie Daten über Kanal B empfängt. Aber du hast Recht, dass ein Switch die Kommunikationen mehrerer PC parallel (PC 1 mit PC 2 und PC 3 mit PC 4) verarbeiten, bzw. organisieren kann. Es können aber nicht 10 Rechner zur gleichen Zeit (parallel) ein Datenpaket an einen Elften senden, was ich eigentlich mit "seriellem Netzwerk" ausdrücken wollte. Diese Pakete würden dann Nacheinander (seriell) den elften Rechner erreichen.
 
Zuletzt bearbeitet:
Zurück