Verbinden von zwei client-sockets
Lassen Sie uns sagen, Java hat zwei Arten von sockets:
- server-sockets "ServerSocket"
- client-sockets oder einfach nur "Buchse"
Stellen Sie sich die situation von zwei Prozessen:
X = Client
Y = Server
Den server-Prozess Y : hat ein "ServerSocket",, das hört auf einem TCP-port
Der client-Prozess X : sendet eine Verbindungsanforderung über eine "Steckdose" zu Y.
Y: Dann ist die accept()
- Methode gibt eine neue client-Typ "Socket",
wenn es Auftritt, die zwei Sockel bekommen, "miteinander",
Also: der socket im client-Prozess, der verbunden ist mit der socket in dem server-Prozess.
Dann: Lesen/schreiben durch sockel X ist wie Lesen/schreiben über socket Y.
Jetzt, zwei Client Sockets Holen Sie sich miteinander!!
Aber...
Was ist, wenn ich die beiden Client-sockets im gleichen Prozess,
und ich möchte, um Sie "miteinander" ?
... auch möglich?
Lassen Sie uns sagen, wie haben zwei client-socket-Holen Sie sich miteinander, ohne Umweg über ServerSocket?
Ich habe es gelöst, indem zwei Threads für das kontinuierliche Lesen Eines und schreiben B,
und andere für das Lesen von B und writng Ein...
Aber ich denke, dass könnte einen besseren Weg geben...
(Die Welt-Energieverbrauch-threads sind nicht notwendig mit der client-server Ansatz)
Jede Hilfe oder Ratschläge würde geschätzt!! Dank
Edit:
Beispiel der Anwendung: "Eine existierende server-Anwendung umgewandelt werden kann, um eine client -",
Zum Beispiel VNC-server, einen client-socket-Verbindung auf den VNC-server und den anderen client-socket erstellt wird (für die Verbindung zu einem mittleren server), dann die Anwendung verbindet die beiden Clients aus der VNC-server ist eine client-Anwendung! Und dann, keine öffentliche IP ist erforderlich.
VNCServer---Anwendung - ---> |middle server| <---Benutzer
- danke für den Kommentar, ich habe es sauber, ein wenig!, und vermeiden Sie die Kappen. Für zu einem missverständlichen Thema habe ich versucht zu erklären, es langsam, danke
- Korrigieren Sie mich, wenn ich falsch bin, aber hier ist das, was ich verstanden habe: Sie haben die Anwendung auf einem server ausgeführt, der VNCServer auf einem anderen und middleServer auf den Dritten server. Benutzer eine Verbindung zu middle-server (ich denke mal, dass eine öffentliche IP). Sie verbinden möchten, zu VNCServer von middle-server, aber Ihr VNCServer ist in einigen intranet-und middle-server außerhalb dieses Netzwerkes. Sie wollen So die Brücke zu den verbindungen. Zu tun, dass Sie geschrieben haben "myApp" (das ist innerhalb des Intranets) öffnet Verbindung zum middle-server, dann VNCServer und Sie möchten, übergeben von Daten an-vom Mittel-server VNCServer. Kommt das nahe?
- Eche, vielen Dank für die Reinigung und die Bereitstellung von mehr info! Entfernt meine down-vote.
- Ja, die kommen in der Nähe, (VNCServer eine Anwendung sein könnte, sogar in der gleichen Maschine), und ja, die Ersten darin sein könnte einem intranet, und ich überbrücken die Anschlüsse, ich habe zwei "MyApp" laufen, Einer im intranet zu interconect VNCServer mit mitten-server (lassen Sie uns sagen, ein clientsocket-zu-clientsocket-Stecker) und in der Mitte server zu erstellen der server (sagen wir ein serversocket-zu-serversocket-Stecker), Ich habe nannte Sie auch "Adapter", da erinnert mich das an die Buchse-Buchse, Stecker-Stecker audio-oder alle-Stecker-Adapter =)
- Kann jemand nur helfen, optimieren Sie den code, wenn Sie buchen Sie es zuerst.
- Ja! Ich glaube, ich habe es! Ich glaube, ich weiß, was Sie wollen. Genau wie TeamViewer. Sie haben einen server, der hält, wer online ist. Dass der main-server hat eine statische öffentliche IP, wo alle clients eine Verbindung herstellen können. Dies bedeutet, dass die "VNCServer" ist nicht wirklich eine große server-Maschine. Es ist auch ein client für das Netzwerk, aber es hat einen ServerSocket laufen. So VNCServer kann sagen, der Haupt-server, wo er ist (öffentliche IP).
Du musst angemeldet sein, um einen Kommentar abzugeben.
Erstens, rufen Sie nicht eine akzeptierte client (server-Seite) das socket eine
Client Socket
. Das ist sehr verwirrend.Unmöglich ist. Sie haben immer einen server-Seite, die akzeptieren, Kunden. Jetzt die Frage: welche Seite der Verbindung sollte der server-Seite?
Dinge, die Sie haben zu denken, über diese Entscheidung:
Ich sehe nicht, was Sie tun möchten, mit diesem Dritten server. Vielleicht hält der VNCServer öffentlichen IP?
*Elister* schrieb, Sie wollen eine Brücke zwischen der client-und der VNCServer. Ich sehe nicht den Vorteil von ihm.
Warum machen Sie nicht sofort eine Verbindung zum VNCServer?
Aber wenn Sie es wirklich wollen, können Sie eine situation wie diese:
Und das ist, wie es aussieht, ohne den Dritten server (Was ich dir empfehlen):
EDIT:
Ich denke ich hab es jetzt:
Haben wir visualisieren Ihre situation so:
(1)
Dem Ersten verbindet, um den Haupt-server. So, dann den main server habe den VNCServer seine IP.(2)
Der client eine Verbindung zum main-server.(3)
Nun die wichtigsten server weiß, wo sich server und client. Dann sendet er an den client, wo der server ist. Dann stellt der client eine Verbindung zu der IP-erhielt er aus den main-server. Das ist natürlich die IP vom VNCServer.(5)
Der VNCServer läuft, ist der server zum akzeptieren der client.Nun desktop-sharing starten können.
Ich denke, dies ist die situation, die Sie empfehlen können.
Natürlich schreiben Sie in Java ist die Ihnen.
Warum würden Sie brauchen, das zu tun?
Wenn Sie wollen, um eine "peer-to-peer" - system, dann müssen Sie nur noch jeden client laufen sowohl einen client-und einen server - socket den server-socket für die Annahme von verbindungen von anderen clients und die client-socket-für das herstellen von verbindungen zu anderen.
ETA: Es war nicht ganz klar, was Sie waren gefragt in der ursprünglichen Frage, aber da Ihr Bearbeiten, wie es scheint, Sie suchen, um eine Art von proxy-server.
In deinem Beispiel, Ihre app schaffen würde, die beiden client-sockets eine Verbindung zu dem Ersten und dem anderen Anschluss an den "mittleren server". Die "Mittel-server" würde dann zwei server-sockets (für Ihre app zu verbinden und eine für die Benutzer zu verbinden. Intern wäre es dann notwendig zu wissen, wie um mit den sockets up und Transfer von Daten zwischen den beiden.
Den ServerSocket erlaubt Ihnen zu hören, für die verbindungen auf einem bestimmten port. Wenn ein server-socket akzeptiert eine Verbindung, es spawnt ein anderer thread, und zieht die Verbindung zu einem anderen port, so dass der ursprüngliche port kann immer noch hören, für zusätzliche Anschlüsse.
Der client initiiert die Verbindung auf dem port bekannt. Dann, in der Regel, der client sendet einige Anfrage, und der server antwortet. Dies wird wiederholt, bis die Kommunikation abgeschlossen ist. Dies ist die einfache client/server-Ansatz, der das web nutzt.
Wenn Sie nicht brauchen, dieser Mechanismus, und die Anfragen kommen entweder von Steckdose zu jeder Zeit, dann die Umsetzung der reader-und writer-threads, so, wie Sie scheint angemessen zu sein.
Intern, Sie verwenden noch warten, Mechanismen, so sollten Sie nicht zu viel zu sehen, die CPU-Auslastung während Sie warten, bis Daten ankommen.
Ich denke, dass Sie noch brauchen, ein Ende zu einem server-socket, weil ich nicht denke, es ist möglich, ein client-socket eine Verbindung akzeptiert. ClientSocket impliziert, TCP, die für die eine Verbindung erforderlich. Wenn Sie verwendet DatagramSocket-Objekt, was bedeutet, UDP, Sie hätten client-zu-client-Kommunikation, ohne eine Verbindung.
Sind Sie versuchen, einen verspottet Steckdose ? Wenn ja, mocking beiden Seiten des Rohres kann ein bisschen komplizierter als nötig.
Auf der anderen Seite, wenn Sie nur wollen, erstellen Sie eine Daten-pipe zwischen zwei threads, die Sie verwenden könnten, PipedInputStream und PipedOutputStream.
Jedoch, ohne weitere Informationen über das, was Ihr versucht zu erreichen, ich kann Ihnen nicht sagen, wenn eine dieser Entscheidungen, die zu Ihnen passt, oder wenn etwas anderes besser wäre.
Einen
socket
(in networking-Bedingungen) besteht aus 2 Endpunkten (client und server app) und 2streams
. Der output-stream des Kunden wird der input-stream des Servers und Umgekehrt.Nun versuchen Sie sich vorzustellen, was passiert, wenn ein thread schreibt eine Menge von Daten in einen stream, während niemand liest... Es gibt Puffer, stimmt, aber Sie sind nicht unbegrenzt und Sie können in der Größe variieren. Am Ende Ihres Schreibens thread auf die Beschränkung des Puffers und wird blockiert, bis jemand befreit den Puffer.
Having said,, Sie sollte jetzt bewusst sein, dass dies brauchen mindestens zwei verschiedenen threads pro Stream: einer, der schreibt, und einer, der liest die geschriebenen bytes.
Wenn Ihr Protokoll-Anforderung-Antwort-Stil, Sie könnten stick mit 2 threads pro sockel, aber nicht weniger.
Könnten Sie versuchen, zu ersetzen, die dem networking-Teil der Anwendung. Erstellen Sie einfach eine abstrakte Schnittstelle, wo Sie können ausblenden, das ganze networking-Teil, wie:
Diese Weise können Sie leicht entfernen Sie das gesamte Netzwerk (einschließlich en- & Entschlüsselung der Objekte, etc.) und minimieren threading.
Wenn Sie möchten, dass die Daten Binär, Sie könnte verwenden Rohre statt oder der Umsetzung Ihrer eigenen streams zu verhindern threading.
Der Geschäfts-oder Verarbeitung von Logik, sollten Sie nicht wissen, über sockets, streams sind low-level genug und vielleicht zu viel.
Aber so oder so: Threading ist nicht schlecht, solange Sie nicht übernutzung es.
Ich verstehe, was Sie nach - ich hatte zur Lösung des gleichen Problems in Situationen, in denen sich der server hinter einem masquerading-firewall mit dynamischer IP. Ich habe eine kleine frei verfügbare Programm, javaProxy eine Lösung zu bieten. Es macht die server angezeigt werden, wie eine client-socket - intern, es ist immer noch ein server, aber javaProxy bietet Spedition-Programm - Meine App in der Beispiel - das schafft client-verbindungen "aus" die server. Es bietet auch ein proxy in der Mitte (Middle-Server, im Beispiel) zum verknüpfen der beiden client-enden zusammen - das client-socket weitergeleitet von der server-und der client-socket von der eigentlichen client versucht, eine Verbindung zum server herstellen.
Den Mittleren Server gehostet wird, die außerhalb der firewall an einer bekannten IP. (Auch wenn wir vorgeben, dies zu tun, ohne server-sockets, jede Verbindung muss sich um eine client-und eine server-Ende und so stellen wir sicher, dass die Mitte-Server auf eine IP, die clients erreichen können.) In meinem Fall habe ich nur ein einfaches hosting-provider, die lassen Sie mich ausführen eines java von der shell aus.
Mit diesem setup konnte ich Zugriff auf remote-desktop-und anderen Dienste laufen, die hinter einer NAT-firewall mit dynamischer IP, mit Zugang von meinem Rechner zu Hause, die war auch hinter einem NAT-Router mit dynamischer IP. Die einzige IP-Adresse, die ich wissen musste war die IP des Mittleren Server.
Als mit threading, die javaproxy Bibliothek ist fast sicher umgesetzt mit threads zu Pumpen-Daten zwischen der client-sockets, die aber nicht verbraucht keine CPU-Ressourcen (oder macht), während Sie blockiert sind warten auf I/O. Wenn java 7 veröffentlicht, mit Unterstützung für asynchrone I/O und dann ein thread pro client-socket-paar wird nicht nötig sein, aber das ist mehr über die Leistungen und die Vermeidung von Beschränkungen für die maximale Anzahl von threads (Stapelspeicher), anstatt den Stromverbrauch.
Als zur Umsetzung dieser selbst mit zwei client-sockets in den gleichen Prozess erfordert die Verwendung von threads so lange wie java ist abhängig von blockierenden I/O. Das Modell ist daraus zu Lesen, die Ende und push-to-end schreiben, so ein thread ist nötig, um daraus zu Lesen, die Ende. (Hätten wir drücken aus der read-end, ich.e asynchornous I/O und dann ein eigener thread pro socket-pair-Mädchen würde nicht nötig sein.)
Warum brauchen wir ein middle server? Wenn Sie nur wollen, zu entlarven VNCServer. Warum nicht versuchen, eine Architektur, die wie folgt
In diesem Fall die Anwendung fungiert sowohl als client (für den Ersten) und als server(für den Benutzer). So haben Sie zu implementieren, sowohl client-als auch server-sockets in der Anwendung und leitet die Daten.
Edit: Zur Kommunikation mit der Ersten Anwendung muss wissen, die IP-Adresse des VNCServer. Benutzer werden nur die Kommunikation mit der Anwendung und muss nur wissen Anwendung die IP-Adresse. Benutzer braucht nicht VNCServer ip-Adresse.
In C aufrufen können Sie socketpair(2) zu bekommen, ein paar Steckdosen angeschlossen, aber ich bin mir nicht sicher, ob java hat keine eingebaute Methode, die gleiche Sache zu tun.
Allgemein gesprochen, eine client-TCP-socket hat zwei enden (lokale und "remote") und einer server-TCP-socket hat ein Ende (denn es wartet auf einen client, um eine Verbindung herzustellen). Wenn ein client verbindet sich zum server, der server intern erzeugt einen client-socket zu bilden, angeschlossen, paar client-sockets, die für die Kommunikation Kanal; es ist ein paar, weil jeder Steckdose, Blick auf den Kanal von einem Ende. Dies ist, Wie TCP Funktioniert (auf hohem Niveau).
Kann man nicht haben zwei client-sockets eine Verbindung zu jedem anderen in TCP, als die low-level-Verbindung-Protokoll funktioniert nicht so. (Sie können eine verbundene paar von sockets erstellt, die Art und Weise in Unix, aber es ist nicht ausgesetzt, die in Java-und Sie sind nicht-TCP-sockets.) Was Sie kann tun ist, schließen Sie den server socket sobald du akzeptiert hast eine Verbindung; für einfache Fälle mag das gut genug sein.
UDP-sockets sind unterschiedlich, natürlich, aber Sie arbeiten mit Datagrammen und nicht Ströme. Das ist ein ganz anderes Modell der Kommunikation.
Wenn Sie möchten, eine
peer-to-peer
Verbindung möchten Sie vielleicht zu prüfen, mitUDP
.UDP
können erhalten von etwas, ohne herstellen einer Verbindung zuerst müssen Sie noch einen server zu sagen, die Kunden, wer Sie sind, receiving data from obwohl.Hoffe, dass dies geholfen.
Den klassischen Java-Ansatz zur Verbindung basierte socket-Kommunikation ist die Einrichtung einer ServerSocket auf eine bekannte IP und port und blockieren Sie es annehmen, Anruf, der (nach einem erfolgreichen Verbindungsversuch) liefert eine neue Buchse mit einer Implementierung bestimmt-port (anders als die ServerSocket's port). In der Regel die zurückgegebenen socket wird an einen handler implementieren Runnable. Handler sind vorübergehend im Zusammenhang mit einer bestimmten Verbindung. Handler können wiederverwendet werden und sind im Zusammenhang mit einem bestimmten Thema in der Regel für die Lebensdauer der Verbindung. Die Blockierung der Natur der klassischen Java-socket-E /a ermöglicht den Anschluss von zwei Steckdosen diente im gleichen thread sehr schwierig.
Aber es ist möglich und nicht ungewöhnlich, zu verarbeiten, sowohl input-und output-streams eines Sockets auf dem gleichen thread und unterstützen eine einzelne Verbindung zu einer Zeit ermöglicht, die Runnable Anforderung fallen gelassen werden, d.h. es wird kein zusätzlicher thread benötigt wird, für die handler und die ServerSocket accept rufen Sie zurückgestellt wird, bis die aktuelle Verbindung geschlossen.
In der Tat, wenn Sie NIO Sie leicht umgehen kann viele verbindungen gleichzeitig auf der gleichen thread mit dem Selektor-Mechanismus. Dies ist eine der wichtigsten Funktionen von NIO, non-blocking I/O zu entkoppeln threads von verbindungen (ermöglicht die sehr hohe Anzahl von verbindungen behandelt werden, die von kleinen thread-pools).
Soweit die Topologie des Systems, das tut mir Leid, ich bin noch nicht klar, was Sie nach sind, aber es klingt wie ein job für einen NAT service oder irgendeine Art von proxy überbrückung der öffentlichen IP auf die private IP.