Java NIO eingehende und ausgehende Verbindungen mit einem Selector

Nightmares

Aktives Mitglied
Hallo,

ich habe bereits einiges an Erfahrung mit NIO und weiß was ich tue. Ich habe bereits eine Lauffähige Version etc jetzt möchte ich aber Eigehende Verbindungen und Ausgehende Verbindungen mit einem Selector realisieren. Die unterscheidung dieser findet mit zwei verschiedenen Objekten die ich ConnectionKey (als wrapper für SelectionKey mit buffern, nachrichten schlangen, etc) nenne stat. Das is auch nicht das Problem. Jedoch schaffe ich es nicht eine ausgehende Verbindung mit einem Selector zu schaffen...

Dazu jetzt erstmal die Frage:
Kann ein Selector überhaupt als "Server" und als "Client" gleichzeitig agieren? Ich denke schon bin da aber nicht ganz sicher. Dazu ist ja die Unterscheidung connectable (client seite) & acceptable (server seite) da. Mein Ansatz war jetzt einfach mit folgender Methode eine Verbindung auf zu bauen.
Wenn ich dies tue bleibt der Key aber bei dem Selector des Zielservers auf connectable stehen

Java:
	protected void connectTo(InetSocketAddress inetSocketAddress) throws IOException {
		SocketChannel socketChannel = SocketChannel.open();
		socketChannel.configureBlocking(false);
		socketChannel.connect(inetSocketAddress);
		socketChannel.register(this.selector, SelectionKey.OP_CONNECT);
	}

Java:
		private void onKeyIsAcceptable() {
		System.out.println("acceptable...");
		// acceptable key; accepting and adding new SocketChannel to
		// register for READ only;
		this.log("Verbose",
				" Acceptable key, accepting and adding new SocketChannel to selector for read only and registering in map",
				null);
		try {
			ServerSocketChannel ssc = (ServerSocketChannel) this.selectionKey.channel();
			SocketChannel sc = ssc.accept();
			
// SIEHE NOTIZ XXX
			if (sc == null) {
				System.out.println("sc null");
				System.out.println(this.selectionKey.readyOps());
				return;
			}
			
			sc.configureBlocking(false);
			sc.socket().setTcpNoDelay(true);
			System.out.println(this.selectionKey.readyOps());

		} catch (IOException e) {
			e.printStackTrace();
			this.log("Verbose", "Acceptable key generated IOException, cancelling... " + e.getMessage(), e);
			this.connectionKey.cancel();
		}
	}
	
	private void onKeyIsConnectable() {
		// attempting outgoing connection...
		System.out.println("connectable...");
		// flag this key as an outgoing connection since we initiate the connection
		this.connectionKey.setOutgoingConnection(true);
		
		try {
			SocketChannel sc = ((SocketChannel) this.selectionKey.channel());
			if (sc.finishConnect()) {
				System.out.println("connectednow");
			}
			
			this.selectionKey.interestOps(SelectionKey.OP_READ);
			
		} catch (IOException e) {
			this.log("Verbose",
					"Connectable key is cancelled or corrupted, cancelling. " + e.getMessage() + e.getStackTrace(),
					e);
			e.printStackTrace();
			this.connectionKey.cancel();
		} catch (NoConnectionPendingException e) {
			this.log("Verbose",
					"Connectable key is cancelled or corrupted, cancelling. There was no connection pending."
							+ e.getMessage() + e.getStackTrace(), e);
			this.connectionKey.cancel();
			e.printStackTrace();
		}
	}

NOTIZXXX: Hier findet nun folgendes Phänomen statt: beim ersten durchlauf Funktioniert alles, allerdings kann ich den Key nicht auf read oder write umflaggen, weil er laut readyOps nur acceptable ist obwohl ich accept() aufrufe und diese methode einen socketChannel zurück liefert.
Beim zweiten durchgang dann jedoch passiert etwas komisches: Der gleiche key ist immer noch acceptable jedoch gibt die accept() methode nichts mehr (null) zurück. Und der Key ist dann für immer in diesem Zustand und die readyOps veränder sich auch nicht (immer noch 16, OP_ACCEPT).

Irgentwie steh ich hier total auf dem Schlauch oder was ich versuche geht einfach nicht.
 

Nightmares

Aktives Mitglied
Okay das ganze Ding ist "aufgegeben".

Es ist nach weiterer Forschung und VIELEN VIELEN tests mir zwar bedingt gelungen (komischerweiße nur unter Linux, unter Windows krieg ichs nicht zum laufen, keine Ahnung warum, theoretisch müsste alles gehen).

Stat dessen habe ich jetzt einfach 2 Selectoren die undabhängig von einander arbeiten. Diese werdem vom selben Thread nacheinander abgearbeitet und alle gewählten Keys an einen ThreadPoolExecutor übergeben. Dadurch entsteht nahezu kein Performence verlust und keine großen nebenwirkungen für den jeweils anderen Selector (alternierende select()'s).

Die Verzögerung liegt bei 100 Verbindungen bei wenigen Millisekunden. Diese delegieren ihre arbeit an die selben ThreadPoolExecutor damit ist fairness zwischen den Selectoren gewährt und die Programmierung deutlich vereinfacht / effizienter da unnütze Threads gespart werden und auch Speicher und die Ressourcen geteilt werden können.

Für interesse am Source Code bitte melden. Den gibts natürlich nicht vollständig, sondern nur den betreffenden Ausschnitt und hinweiße auf was geachtet werden muss.
 

Domi F

Mitglied
Ein solches Problem hatte ich noch nie, ich verwende nur einen Selector für alle SocketChannels.

Was mich aber wundert bei deiner Beschreibung, dass du versuchst den SelectionKey von Accept auf Read zu setzen. Du musst den neuen SocketChannel mit Read registrieren (register). Den mit Accept kannst so lassen, wenn du weitere Verbindungen erwartest, oder sonst halt entfernen.

Hast du den SelectionKey der auf Accept reagiert hat aus dem Set (selector.selectedKeys()) entfernt? Wenn ich das nicht tue, habe ich auch das Verhalten, dass accept plötzlich null zurück gibt.
 

Nightmares

Aktives Mitglied
Hallo,

ja da habe ich mich unklar ausgedrückt. Natürlich muss der SocketChannel der mittels serverSocketChannel.accept() angenommen wird mit dem Selector per .register(selector,ops) registriert werden. Außerdem gibt es hier zu noch ein Update: Es ist mit jetzt doch gelungen. So wie es aussieht war das ganze eher ein Problem meines Resource Caches (ich Cache alles so gut wie möglich um Objekt Erstellungen zu minimieren). Hatte mich bei meiner Klasse, die die Änderungen Speichert bis diese vom Selector Thread vor dem select() ausgeführt werden etwas vertan. Die Objekte wurden bereits wieder dem Pool hinzu gefügt bevor diese fertig waren. (Einfach ein Zeilendreher was die 2 betreffenden Methoden angeht...).

Zu deiner Frage wegen den .selectedKeys(), ich habe und werde dieses nie modifizieren. Das ist auch gar nicht nötig oder vor gesehen.

Das Teil läuft jetzt wie geschmiert. 10k Verbindungen, die je zwischen 4 Nachrichten pro Sekunde schicken und empfangen: nahe zu 0% CPU last auf meinem i7 980 mit 6x 3,3ghz.

Wenn es nichts zu tun gibt ist das ganze Ding praktisch IDLE, Selector bleibt einfach bei select() bis was zu tun ist. Das ganze Dinge läuft auch noch nach 12 Stunden (atm hab ich nen Test Client mit 10k Verbindungen zu einem Test Server die sich Gegenseitig ints schicken, diese hoch bzw runter zählen und zurück schicken) stabil ohne Speicher Probleme (Verbrauch ist nicht größer geworden).

Was noch fehlt ist das meine Load Balance etwas fairer wird. Ist zwar auf lange Zeit (mehrere Sekunden und mehr) absolut fair aber zwischendurch wenn immer wieder "Datenstöße" ankommen nicht direkt fair, hier dauert es etwas bis der Server das erkennt ebenso bei hohen Latenzen muss ich noch gucken wie ich da richtige fairness erreiche. Hab zwar paar Ansätze um das zu verbessern aber noch nichts konkretes.
 
Zuletzt bearbeitet:

Kr0e

Gesperrter Benutzer
Ab JDK 7 gibts Asynchrone-Channels, da kannste dir den ganzen Kram mit Selektors sparen. Die interne Impl. ist dann genauso wie beim Selektorprinzip je nach OS optimiert und handled verdammt viele Verbindungen. Die Benutzung ist seeehr viel einfacher... Ich würde mich heutzutage nicht mehr mit Selektors rumärgern. Das Prinzip ist sowieso überholt...
 

Kr0e

Gesperrter Benutzer
Welche Nachteile ? Mir fiele nur einer ein: Man muss Java7 benutzen...


Um das nochmal klar zu formulieren: AIO macht unter der Haube etwas ähnlcihes wie der Selektor... Nur eben viel einfacher benutzbar als Nio1.4. Es ändert sich nur die Fassade! Man könnte z.b. beim Selektorprinzip denken, dass die Socketfunktion "select" benutzt wird, das trifft aber auch nicht überall zu. Unter Linux wird epoll und unter Windows die WSASelect Funktion benutzt, welche wiederum auf den CompletionPorts basiert. Selektors verkomplizieren einfach nur das Ganze, vorallem weil Selektors eigentlich als API nicht geeignet ist, denn wie schon erwähnt, haben unterschiedliche OS unterschiedliche Konzepte und da ist ein AsynchronousChannel einfach besser geeignet als Abstraktion..
 
Zuletzt bearbeitet:

Lumaraf

Bekanntes Mitglied
Wenn man vor hat häufig Daten von einer Datei in ein Socket oder umgekehrt zu übertragen ist NIO etwas schneller durch Methoden wie z.b. FileChannel#transferTo(long position, long count, WritableByteChannel target). Insofern man nicht auf die etwas bessere Performance in dem speziellen Fall angewiesen ist und Java 7 verwenden darf ist AIO eigentlich fast immer zu bevorzugen.
 

Nightmares

Aktives Mitglied
Was mich an NIO2 irgendwie stört nachdem ich mich jetzt eine Weile damit beschäftigt habe ist, dass das ganze relativ unübersichtlich geworden ist. Die ganze Sache mit den Future/CompletionHandler ist mehr als kompliziert. Dagegen sieht NIO richtig "freundlich" aus und ist leichter zu benutzen. Da verzichte ich lieber erstmal auf den kleinen Geschwindigkeits Vorteil. Wenn ich wirklich Performance brauche schreib ich den Server halt in C.
 

Kr0e

Gesperrter Benutzer
Lustig, ich finde es genau umgekerht! Aber ok, jedem das Seine. Ich persönlich mag das asynchrone Konzept und ich komme viel besser damit klar, als mit reinem NIO. Wenn ich was mit NIO mache, würde ich sowieso ein Framework nehmen, wie Netty,Mina etc... Aber vlt liegts auch daran, dass ihc mich shcon lange mit Event-driven/Concurrency beschäftige, wodurch das Konzept mir sehr vertraut ist.,..

SChönes Wochenende ;)
 

Nightmares

Aktives Mitglied
NIO ist genau so Event-Driven wie NIO2. Und das Prinzip mit dem Selector ist viel übersichtlicher: Es wird dir gezeigt wofür dein Key gerade zugelassen ist, was er möchte bzw. man meldet ein Interesse zu schreiben. Dann hat man seine Warteschlange für Eingehende & Ausgehende Daten. Und für NIO habe ich selber ein "Framework" geschrieben was übrigens gleiche Performence wie Netty erreicht mit meinem eigenen Protokoll, dass jeden Java Primitiven Datentyp übertragen kann sowie deren Arrays mit nahezu keinem Overhead, wahlweise Kompression und gerechte Verteilung der Bandbreite mit verschiedenen Einstellmöglichkeiten

EDIT:
Was mir bei NIO2 irgendwie fehlt / mich stört ist das Future Konzept. Ich finde es unnötig, dass ich diese Objekte dann auch noch habe und überprüfen muss. Die Alternative sind die CompletionHandler, die einem mehr Möglichkeiten geben. Was ein Fortschritt ist, ist z.B. das Attachment, das jetzt nicht mehr nur ein Object ist das man zurecht casten muss sondern Generalisiert werden kann. Was mir aber fehlt ist, das ich keine Liste der "arbeiten" kriege was mich effektiv um einen Teil meiner Möglichkeiten zur Gerechten Verteilung der Leistung bringt.
 
Zuletzt bearbeitet:

Kr0e

Gesperrter Benutzer
Also ich verstehe deine Kritik nicht wirklich. Hilft dir folgender Screencast um meine Begeisterung an NIO2 zu verstehen:

Parleys.com - The Next Generation E-Learning Platform

NIO2 ist außerdem schneller/performanter und zwar ganz einfach deshalb, weil hin und wieder mehrere Schreib/lesevorgänge innerhalb eines Threadcontexts geschehen und du dir damit etwas scheduling sparst. (Am Ende des Screencast siehst du was ich meine)

Ich persönlich empfinde das Selektorprinzip ätzend und nichts für ungut für dein "eigenes" NioFramework. Aber ich finde die Aussage "gleich wie NEtty" etwas krass. 1. glaube ich nicht , dass du umfassende Tests gemacht hast, die nötig wären, für eine quantifizierbare Aussage wie diese. Und 2. Liegt Netty's Stärke vorallem im guten Threading Modell. DAs ist überhaupt das Wichtigste an allen NioFrameworks. Scheduling kann einem sehr viel kaputt machen, aber wenn jeder User einen dedizierten Thread hat (Ein konstanter Thread bedient mehrere User), dann leidet die Flexibilität. Sprich du müsstest mehrere Tausend Verbindungen simulieren mit unteschiedlichen Anforderungen und Requestgrößen mit unterschiedlichen Latenzen. NEtty ist in sofern schon arg optimiert. Sprich wenn dein Framework mit 100 Clients gut klappt, dann heißt das noch überhaupt nichts. 100 Cleints wären mit Threads übrigens besser bedient -> IO.

- Übrigens einer der Gründe warum AIO so genial ist: Aufgrund des gegebenen Threadpools und des internen Modells muss man als Programmierer endlich nicht mehr Frameworks benutzen, weil es von Hand zu aufwendig wäre. Warum gibt es wohl sooo viele Frameworks für NIO ? Genau, weil es von Hand einfach zu aufwendig ist. NIO ist ein wirklcih unübersichtliches API und orientiert sich noch am alten Berkley select() was aber überholt ist. -

Du redest von einer "Liste der Arbeiten", das verstehe ich nicht. Bei AIO kann immer nur ein Befehl gleichzeitig abgearbeitet werden, sonst fliegen eh Read/WRitePending Exceptions. Für solche Listen ist der PRogrammierer zuständig und es geht uach garnicht anders, gerade für WriteQueues...

AIO hat ein gutes Konzept, ist viel leichter zu verwenden (Threading ist ja schon abgedeckt, im Gegensatz zu NIO) und bingt auch noch ein paar Prozent mehr Leistung. Absolut kein Grund nicht zu wechseln. Allerhöchetns der, dass AIO Java 7 ist und alles nocht recht neu. Warte mal ein paar Monate ab, dann wird sich das durchsetzen... War ja bei NIO auch so.

Und der Punkt, dass es kaum Tuts gibt, ist hinterlich, gerade weil noch sowas wie "Best-Practices" fehlt, aber das merkt man selbst, wenn man ein wenig damit rumspielt und iwann hat man das Prinzip verstanden...
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
D HTTP Apache-HttpClient/UNAVAILABLE (java 1.4) Netzwerkprogrammierung 18
M JAX-WS unter Java 17 plötzlich nicht mehr möglich Netzwerkprogrammierung 5
K Java RMI bricht ab wenn Remote eine Methode ausgeführt werden soll Netzwerkprogrammierung 5
M HTTP Let's Encrypt und Java Trust-Store Netzwerkprogrammierung 6
JaXnPriVate Java HTTPS Server (Secure Sockets) Netzwerkprogrammierung 15
Tobero Java serversocket nicht nur zuganglich für localhost Netzwerkprogrammierung 6
D path-Variablen in eine URL hinzufügen mit Java 1.8 Netzwerkprogrammierung 2
D WebSocket Server mit HTML Client und Java Server Netzwerkprogrammierung 5
S Von Java auf passwortgeschützten Server zugreifen + Umgang mit Ports Netzwerkprogrammierung 28
S Probleme bei Java-Installation auf Server (Linux/Shell/Terminal) Netzwerkprogrammierung 6
S Java: Anbindung an einen realen Server? (+ Portfreigabe) Netzwerkprogrammierung 8
H Socket Chat entwickeln mit Java Server Client Netzwerkprogrammierung 4
x46 Java SSLContext erstellen mit SSL-Zertifikat Netzwerkprogrammierung 1
P Jenkins Login per Java Download Manager Netzwerkprogrammierung 15
N Java socket Programmierung Filme verschicken Netzwerkprogrammierung 20
S HTTP Post?!? - Java Server Netzwerkprogrammierung 7
F Verbindung zu einem LDAP Server über Java Netzwerkprogrammierung 4
K Java Websocketserver Problem | Android to Pi Netzwerkprogrammierung 1
R Anfängerbeispiel: Suche Java-Anwendung die http-Anfragen in Tomcat liest Netzwerkprogrammierung 8
V Browsergame mit Java(WebSocketServer) als Backend? Netzwerkprogrammierung 5
platofan23 Socket Java Socket mit DynDns nicht erreichbar Netzwerkprogrammierung 6
S Fragen zu Java Webservice mit Axis2 Netzwerkprogrammierung 0
M Mit Java Mail Mails an Webmailer schicken Netzwerkprogrammierung 1
mor16Euro HTTP Php website mit Java aktualisiern Netzwerkprogrammierung 6
T HTTP JAVA Browser Konsolenanfrage(JavaScript) Netzwerkprogrammierung 7
L Socket Wie kann man in Java die Anzahl der Objekte in einem InputStream sehen ohne ihn durchgehen zu müssen Netzwerkprogrammierung 1
M Socket Verbindung Matlab(Server) Java(Client) Netzwerkprogrammierung 1
M Socket peer to peer Verbindung zwischen Java und Matlab Netzwerkprogrammierung 0
L Remote Desktop per Java steuern Netzwerkprogrammierung 4
F Server für Java Applikationen Netzwerkprogrammierung 16
J Webserver mit Java schreiben? Netzwerkprogrammierung 4
D JAVA RMI Netzwerkprogrammierung 1
K HTTP Mit Java HTML Codeauslesen um damit zu arbeiten Netzwerkprogrammierung 7
V Kann man mit Hilfe eines Java-Programms den Zugriff auf bestimmte Internetseiten verhinden? Netzwerkprogrammierung 3
J HTTP [Java 9] Neuer HTTP Client - Tutorial Netzwerkprogrammierung 3
T Mikrofonaudio über Java Server an Webbrowser streamen Netzwerkprogrammierung 13
A Bestimmter URL/Certificate per Java immer vertrauen (Trustmanager/HostnameVerifier) Netzwerkprogrammierung 1
T VPN-Verbindung über Java Netzwerkprogrammierung 4
M HTTP PATCH Request mit Java ausführen Netzwerkprogrammierung 2
Niggo_ Probleme mit Java Mail Netzwerkprogrammierung 14
Aruetiise Socket Java Programm auf Server Netzwerkprogrammierung 3
L FTP Java Interpreter unterbindet SSL Handshake Netzwerkprogrammierung 2
C IFrame mit java auslesen Netzwerkprogrammierung 1
A FTP wie kann ich von java auf datei in fpt://192.168.178.1 lesen/schreiben? Netzwerkprogrammierung 3
C Datensammlung mit Java RMI Netzwerkprogrammierung 0
K Java Jsoup : OnLoad Netzwerkprogrammierung 0
S Java Chat Server Netzwerkprogrammierung 8
Carres HTTP Vorhandenen Session-ID Cookie von Firefox, Chrome oder IE in Java verwenden Netzwerkprogrammierung 2
B Java+Grbl: G-Code Befehle mit Java an Arduino senden und lesen Netzwerkprogrammierung 1
Z HTTP HTML Element auslesen in Java Netzwerkprogrammierung 1
T Socket Java Programm hängt sich auf bei dem versuch von einem Socket scanner Daten zu erhalten. Netzwerkprogrammierung 1
Thallius HTTP HTTPS unter Java 1.6 schlägt fehl Netzwerkprogrammierung 4
Thallius Java Application über ZScaler benutzer? Netzwerkprogrammierung 0
P Chat in Java Netzwerkprogrammierung 3
C java.net.ConnectException: Operation timed out? Netzwerkprogrammierung 2
M Java Eingabe auf FTP Server übergeben Netzwerkprogrammierung 4
T curl request in java umwandeln Netzwerkprogrammierung 4
M Socket Java Server: NullPointerException Netzwerkprogrammierung 4
J Java Server empfängt php inhalt nicht Netzwerkprogrammierung 1
I Socket Kommunikation C / Java Netzwerkprogrammierung 2
H Machbarkeitsfrage: TCP/IP Client (z.B. Netty) für Java Web Applcation Netzwerkprogrammierung 1
L Java RMI Objekt konsistenz Netzwerkprogrammierung 1
H Portforwarding umgehen in Java? Netzwerkprogrammierung 5
D Response in Java Servlet erzeugen Netzwerkprogrammierung 0
X Mit Java eine Applikation auf einem anderen Windows Rechner (Windows Server 2008) starten Netzwerkprogrammierung 1
E HttpUrlConnectionExample cannot be resolved to a type / Java 8 Netzwerkprogrammierung 1
F Socket Java Server mit Android App, Antwort vom Server an App Netzwerkprogrammierung 5
M Java-Programm aus dem Web laden Netzwerkprogrammierung 3
S HTTP-Requeste von Browser mit Java sniffen? Netzwerkprogrammierung 9
J access denied (“java.net.SocketPermission”…) mit Java 8 Netzwerkprogrammierung 1
N CURL requests in Java Netzwerkprogrammierung 6
P Kritische Java-Anwendung und Citrix veröffentlichen Netzwerkprogrammierung 1
F Java Server Scanner oder InputStream kann nicht gelsesen werden! Netzwerkprogrammierung 6
1 Netty NIO oder Java IO Netzwerkprogrammierung 2
1 Via Java mit WLAN Netzwerken verbinden Netzwerkprogrammierung 5
J Java Service Wrapper Netzwerkprogrammierung 1
K Mit Java ASPX Webseite fern steuern Netzwerkprogrammierung 2
H Socket Java | Server sendet Nachricht nur wenn vorher eine JOptionPane-Nachricht ausgegeben wurde. Netzwerkprogrammierung 2
K Emailsenden via Java Applikation Netzwerkprogrammierung 5
L Mit Java über PHP in MySQL anmelden (Login script) Netzwerkprogrammierung 3
C Java Chat Admin Kenzeichnung Netzwerkprogrammierung 14
P PHP Script per Java ausführen Netzwerkprogrammierung 2
P PPTP Protokoll für JAVA Netzwerkprogrammierung 14
T php/java-bridge Netzwerkprogrammierung 16
D Webseite(mit JavaScript-Element) mit Java auslesen Netzwerkprogrammierung 0
G Multiple Clients and one Server --> java.lang.NullPointerException Netzwerkprogrammierung 1
E Java Server übers Internet erreichen Netzwerkprogrammierung 4
D Socket Error: java.lang.NullPointerException Netzwerkprogrammierung 1
windl AirPlay mittels Java Netzwerkprogrammierung 0
R Email mit Java API Netzwerkprogrammierung 1
P Java Deauth / Deauthentication request Netzwerkprogrammierung 10
F Socket Java - Server/Client simple Netzwerkprogrammierung 1
E HTTP java.lang.IllegalArgumentException: protocol = http host = null Netzwerkprogrammierung 1
R Java - Socketprogrammierung Netzwerkprogrammierung 10
B Methoden und Konstruktoren von Java.net package werden nicht geladen Netzwerkprogrammierung 2
L Email versenden mit Java funktioniert nicht, Fehlermeldungen: MessagingException & SocketException Netzwerkprogrammierung 10
V Templates für Java Client rabbitmq Netzwerkprogrammierung 4
N Socket java.net.ConnectException Netzwerkprogrammierung 5
A Java Server - IOS Client Applikation Netzwerkprogrammierung 20
V json_encode in java?? Netzwerkprogrammierung 3

Ähnliche Java Themen

Neue Themen


Oben