Socketverbindung über das Internet - Timeout?

Extremefall

Bekanntes Mitglied
Hallo,
ich würde gerne über die öffentliche IP eine Verbindung zwischen zwei Computern aufbauen und darüber dann Daten austauschen. Ich habe schon ein kleines Programm dazu geschrieben:
Die Klasse Client:
Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
	static Socket clientSocket;

	public static void connectToSoccet(InetAddress IP, int port) {
		try {
			Socket clientSocket = new Socket(IP, port);
			OutputStream out = clientSocket.getOutputStream();
			out.write(112 + port);
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

Die Klasse Server:
Java:
import java.net.*;
import java.io.*;

public class Server {
	public Server(int port) throws Exception {
		ServerSocket socketServer = new ServerSocket(port);
		while (true) {
			Socket client = socketServer.accept();
			InputStream input = client.getInputStream();
			BufferedReader stdIn = new BufferedReader(new InputStreamReader(
					input));
			String userInput;

			while ((userInput = stdIn.readLine()) != null) {
				System.out.println("echo: " + input.read());
			}
		}
	}
}

Auf PC A wird dann der Server gestartet:
Java:
Server server = new Server(4447);

Auf dem anderen PC anschließend der Client, der sich zum Server verbinden soll und einen Outputstream übertragen soll:
Java:
Client.connectToSoccet(InetAddress.getByName("xx.xxx.xxx.xxx"),4447);
Wieso erhalte ich wohl folgende Fehlermeldung:
Code:
java.net.ConnectException: Connection timed out: connect
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.PlainSocketImpl.doConnect(Unknown Source)
	at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
	at java.net.PlainSocketImpl.connect(Unknown Source)
	at java.net.SocksSocketImpl.connect(Unknown Source)
	at java.net.Socket.connect(Unknown Source)
	at java.net.Socket.connect(Unknown Source)
	at java.net.Socket.<init>(Unknown Source)
	at java.net.Socket.<init>(Unknown Source)
	at Client.connectToSoccet(Client.java:14)
	at GUI.<init>(GUI.java:14)
	at GUI.main(GUI.java:32)
Die IP habe ich mir eine Minute vorher erst angeschaut.

Ich hoffe, ihr könnt mir weiterhelfen.
Danke schonmal.
 
Ist die verwendete IP Adresse tatsächlich die IP des "Servers"? Wie sind die Rechner verbunden? Ist ein Router oder eine Firewall dazwischen? Können die Rechner sich "sehen"? Setze mal einen ping vom Clientrechner an die IP des Servers ab.
 
Die Rechner können einander meines Wissens nach nicht sehen (ich finde den anderen Rechner nämlich nicht im LAN). Es gibt einen Router. Ich habe die Firewall bei beiden Rechnern deaktiviert, doch es ändert nichts. Das "pingen" mit der IP funktioniert.

Was kann ich noch machen und wie? Habe ich eventuell etwas falsch programmiert? Oder was muss ich noch machen?

Was kann ich denn mit NAT machen? Kenne mich da zugegebenermaßen nicht so gut aus. Denn das Programm sollte eigentlich funktionieren, ohne dass alle Ports erst noch manuell eingestellt werden müssen.
 
Zuletzt bearbeitet:
also gut,

was zu Hölle meinst Du mit "offentlicher IP"? ... Internet? ... willst Du 2 Rechner in 2 verschiedenen DSL-Einwahlen verbinden? ... das würde auch erklären wieso Du den "anderen" Rechner nicht im LAN findest ... in dem Fall kommst Du um NAT - und dessen Probleme - nicht herum (udiags)

wenn Du die Rechner verbinden willst ohne an Ports im DSL-Gerät rumzuschrauben, brauchst Du einen öffentlichen Server ... dazu würde ich Dir aber mit Deinen Netzwerkkenntnissen nicht raten
 
Ich denke das noch fehlende Stichwort ist "Portforwarding" in Verbindung mit dem Router, hinter dem der "Server" steht. Dann klappts auch mit dem Verbindungsaufbau.

- Alex
 
Über Port-Forwarding weiß ich, dass dadurch die Verbindungen über den Port "weitergelitet" werden, also bestimmt wird, welcher Rechner der Zielrechner ist.

Kann man so etwas auch durch reinen Quellcode umsetzen? Wenn ja, wie? Hättet ihr passende Tutorials (am besten mit Code)? Denn es soll zur Kommunikation zwischen zwei PCs zwei Server geben.
 
Durch reinen Code ist das nicht zu bewerkstelligen. Dein Router müsste hierfür mindestens UPnP Unterstützen und aktiviert haben. Erst dann kann man per Software das Portforwarding automatisch einrichten. Mir ist allerdings kein Standard-Router bekannt der das per default aktiv hat. Wenn, dann muss man es erst noch einschalten. Und dann kann man auch gleich das Portforwarding konfigurieren.
 
Es gibt aber doch auch Programme, die eine Verbindung zu einem anderen Computer über IP aufbauen oder etwa nicht? Wie gehen diese vor? Welche Alternativen gäbe es zu Sockets?
 
Ich habe nun Port-Forwarding für den Port 4447 beim Router für UDP und TCP eingestellt. Nun habe ich auch den Server auf PC A gestartet und auf PC B habe ich den Clienten gestartet. Auf PC B habe ich zusätzlich noch das Programm IPHider am Laufen, damit Server und Client nicht die selbe IP haben. Im Programm lasse ich mir auch die iP ausgeben und diese ist unterschiedlich.

Es gibt nun keine Fehlermeldungen mehr, allerdings wird auch nichts auf dem PC A ausgegeben. Woran mag das liegen? Habe ich einen Fehler in meinem Code? Ich dachte, dadurch wird an den SocketServer die Zahl gesendet und dort ausgegeben. Von der Syntax ist es alles also wohl fehlerfrei.
 
Was ist wohl der Fehler? Es gibt keine Fehlermeldungen. Wieso wird auf dem PC, der als Server fungiert, nicht die Zahl ausgegeben? Habe nun doch den virtuellen Server mit dem Port erstellt. Bin am verzweifeln, da es keine Fehlermeldung mehr gibt.
 
Beim Debuggen habe ich leider nichts gefunden, was aber auch nichts heißen muss. Könnt ihr mich eventuell auf einen Fehler aufmerksam machen? IP etc. stimmt und es gibt weiterhin keine Fehler. Port-Forwarding habe ich am Router gemacht.
 
Java:
            while ((userInput = stdIn.readLine()) != null) {
                System.out.println("echo: " + input.read());
            }
Du ließt zunächst eine komplette Zeile. Danach versuchst du nochmal ein Zeichen zu lesen. Soweit ich das sehe sendest du aber nur eine Zeile.
Lass dir hier doch hier einfach mal userInput ausgeben.

EDIT:
evtl. musst du auch noch nen Zeilenumbruch senden, sonst kann es sein dass readLine nichts liest.
 
Für userInput wird nichts ausgegeben. Es wird auch nicht das Wort "echo" ausgegeben. Das bedeutet im Umkehrschluss, dass die While Schleife false ergibt. Wie kann ich denn einen Zeilenumbruch einfügen? Denn mit Write übergebe ich ja einen Integer Wert. Da kann ich doch nicht einfach einen String anhängen.
 
Nimm z.b. statt nem einfachen Outputstream einen PrintWriter, da hast du die Methode println. Dann wird automatisch ein Zeilenumbruch am ende gesendet.
 
Ich habe es nun mit dem PrintWriter probiert, leider ändert es nichts:
Java:
 PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
            printWriter.print("hhi");
            printWriter.flush();
Kann man vielleicht erst einmal irgendwie prüfen, ob eine Verbindung zum SocketServer erfolgreich war? Das ist irgendwie ziemlich komisch, dass es immer noch nicht funktioniert. :/
 
du musst wie gesagt ein newLine mitsenden, damit die readLine methode eine ganze Zeile lesen kann, woher soll die sonst wissen dass die Zeile zu ende ist?
Verwende also println statt print.
 
clientSoccet.isConnected() liefert true.Da sollte der Fehler also nicht liegen. Die Ausgabe auf dem PC, wo ich die Klasse Server gestartet habe, erscheint dennoch nicht. Auch nicht mit dem PrintWriter. Noch irgendjemand eine Idee, wo der Fehler liegen könnte?

Hier noch einmal eine Zusammenfassung zur Übersicht:
- Port-Forwarding auf Port 4447 über NAT beim Router aktiviert
- Client verwendet das Programm IPhider, damit die IP von Client und Server nicht übereinstimmen
- Firewall bei Client und Server Rechner ist deaktiviert

Code:
Client-Klasse:
Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
	static Socket clientSocket;

	public static void connectToSoccet(InetAddress IP, int port) {
		try {
			Socket clientSocket = new Socket(IP, port);
			PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(
					clientSocket.getOutputStream()));
			printWriter.println("hhi");
			printWriter.flush();
			System.out.println(clientSocket.isConnected());
			clientSocket.close();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

Server-Klasse:
Java:
import java.net.*;
import java.io.*;

public class Server {
	public Server(int port) throws Exception {
		ServerSocket socketServer = new ServerSocket(port);
		while (true) {
			Socket client = socketServer.accept();
			InputStream input = client.getInputStream();
			BufferedReader stdIn = new BufferedReader(new InputStreamReader(
					input));
			String userInput;

			while ((userInput = stdIn.readLine()) != null) {
				System.out.println("echo: " + userInput);
			}
		}
	}
}

GUI-Aufruf:
Java:
Client.connectToSoccet(InetAddress.getByName("xxx.xxx.xxx.xx"),4447);
// oder für den Server
Server server = new Server(4447);
 
Zuletzt bearbeitet:
Ist vielleicht eine blöde Frage, aber:

Funktioniert es den wenn Server und Client Softwäre auf dem selben Rechner laufen?
Zwischen zwei Rechnern im selben LAN?
 
Einen lokaler Socket habe ich auch schon ausprobiert. Mit diesem Code macht es wenig Sinn, da man für einen Rechner keine zwei Ips vergibt. Außerdem würde ich dann über den localhost eine Verbindung aufbauen und da müsste der Code erneuert werden.

Liegt es wohl an der Verbindung? Aber dann sollte es doch eine Exception geben oder? Wo kann der Fehler liegen?

Ps.: Vielen Dank schon einmal für eure Hilfe. Ich hoffe, dass ihr mir noch weiterhelfen könnt.
 
Hi,

die Antwort steht doch schon weiter oben. Du möchtest eine ZEILE einlesen hast aber keine Zeilenende.

Dieser Code scheint höchsten 50 Zeilen zu haben, wo ist das Problem das eben auf einem lokalen Rechner zu testen.

Ich teste alle meine Anwendungen auf einem Rechner.

Gruß,

Martin
 
Auf einem Rechner klappt es mit dem localhost. Es wird der Text ausgegeben. Also es klappt wirklich. Wo könnte also sonst der Fehler liegen? Muss ich denn bei der Socketverbindung eine iNetAddress als Parameter angeben und ist mein Code dafür richtig oder wie löse ich das Problem? Also der Code scheint ja sonst schon zu passen 😉
 
Das Programm läuft lokal über den localhost, doch nicht über die IP. Wo liegt also der Fehler? Ich verwende die IP, die sich auch über Seiten wie wieistmeineip.de anzeigen lässt.
 

Zurück
Oben