# Empfangen klappt Senden nicht - Connection timed out



## Thaflasher (28. Nov 2011)

Hi Forum,

ich habe das Problem das mein Server Daten empfangen kann, aber leider keine sendet weil er die Verbindung nicht aufbauen kann.

Unter Windoof im Netzwerk ist es kein Problem mit der Verbindung, senden und empfangen klappt wunderbar. Nun läuft das Programm unter Debian Linux auf einem Server mit Portumleitung und schon wird die Sache ungemütlich.

Von außen verbinde ich mich auf den Port 8008 und werde auf 1024 weiter geleitet. -> Server empfängt und verarbeitet.

Beim zurück Senden an die Netzwerk-ip des Clients bekomme ich nun leider eine Connect Exception: Connection timed out

Mit "ping myClientIP" finde ich auch die ip d.h. es sollte generell möglich sein eine Verbindung aufzubauen.


Nun meine Fragen:

Muss ich nun den Server ansprechen der mich weitergeleitet hat, damit dieser mich wieder in das Netzwerk weiter leitet (Wenn ja wie stellt man das an - Stichwort?  ) 

oder 

ist es möglich das der Server der mich weiter leitet nur beim Eingang eine Rolle spielt und ich beim Ausgang keine Portumleitung habe? 


Nachdem ich am Server die Routen, listen-ports etc überprüft habe und das alles passt weis ich leider nicht so recht nach was ich noch suchen könnte ;(

Danke für Hilfe!


----------



## irgendjemand (28. Nov 2011)

ohn source wird aus deiner beschreibung das problem leider nicht klar ...

und in wie fern meinst du das mit daten zurück senden ?

verwendest du TCP oder UDP ?

wenn TCP : wo ist dein problem ? das ist eine stehende verbindung *bis du sie beendest oder aus anderen gründen die verbindung verloren geht*

wenn UDP : Firewalls ... thema : udp hole punching ... *ist hier nicht sehr beliebt und viele meinen ich hätte damit getrollt ... aber es ist eine einfache und saubere lösung ... vor allem da diese offiziell durch STUN beschrieben ist ... UPnP ist dagegen wahlfrei und kann meist sogar explizit deaktiviert werden*

auch komisch : warum wird der port umgeleitet ? und dann noch auf einen solchen schwellen wert ?

ich glaube hier ist wirklich source und eine bessere beschreibung der infrastruktur nötig um dir zu helfen ...


----------



## Thaflasher (28. Nov 2011)

Ich benutze TCP und die Verbindung wird beendet sobald die Datenübertragung beendet ist. Anschließend baue ich eine neue Verbindung auf um eine Antwort zurück zu schicken.

Der Sender ist ein Java Prog auf einem Debian Linux Rechner, der Part der Empfangen soll ist ein Android Handy.

*Der Server der senden soll:*


```
public class DataSender implements Sender, Runnable {

	private Worker worker;
	LogStation ls;
	
	public DataSender(Worker worker){
		this.worker = worker;
	}
	
	public void sendData(ArrayList<String> instructions, OutputStream out) throws IOException{
		DataOutputStream dos = new DataOutputStream(out);

		for (int i = 0; i < instructions.size(); i++) {
			dos.writeUTF(instructions.get(i));
		}

		dos.flush();
		dos.close();
	}

	@Override
	public void run() {
		Socket socket;
			int counter = 0;
			while(true){
			try {
				socket = new Socket();

				SocketAddress remoteBindPoint = new InetSocketAddress("xx.xx.xx.117", 1024);
				socket.setReuseAddress(true);
				socket.connect(remoteBindPoint, 30000);
				sendData(worker.getInstructions(), socket.getOutputStream());
				socket.close();
				break;
			} catch (ConnectException e) {
				e.printStackTrace();
				counter++;
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e1) {
				}
				if(counter==3){
					counter=0;
				break;}
				else{
					continue;
				}
			} catch (SocketException se){
				se.printStackTrace();
				break;
			} catch (IOException e) {
				e.printStackTrace();
				break;
			}
			}
	}
}
```

*Der Receiver der annehmen soll:*


```
public DataReceiver(int port, LinkedBlockingQueue<ArrayList<String>> receiverQueue) throws IOException{
		this.port = port;
		this.receiverQueue = receiverQueue;
	}
	
	public void startConnect() throws IOException, NoServerException{
		ServerSocket sskt = null;
		Socket socket = new Socket();
		try{
			sskt = new ServerSocket(port);
			sskt.setReuseAddress(true);
			sskt.setSoTimeout(30000);
			socket.setReuseAddress(true);
			socket.setSoTimeout(30000);
			socket = sskt.accept();
			receiveData(socket.getInputStream());
			socket.close();
			sskt.close();}
		catch (SocketTimeoutException e) {
			if(sskt != null){
				if(!socket.isClosed()){
					socket.close();}
				if(!sskt.isClosed()){
					sskt.close();
				}
			}
			throw new NoServerException();
		}
		}
	
	
	public void receiveData(InputStream is) throws IOException {
		DataInputStream dis = new DataInputStream(is);
		ArrayList<String> receiveList = new ArrayList<String>();
		
		while(true){
			try {
				String holder = dis.readUTF();
				receiveList.add(holder);
			} catch (EOFException e1){
				break;
			} catch (IOException e2) {
				break;
			}
		}
		receiverQueue.offer(receiveList);
		dis.close();
		is.close();
	}
}
```

Hier hab ich die IP fest angegeben, da ich bemerkt habe das die socket.getInetAddress mir die IP des Servers gibt der mich zuletzt umleitet und nicht die IP ist zu der er eigendlich connecten soll. :autsch:

Der Port in dem src ist 1024.

zum Ablauf:

Ich verbinde mich mit einer ip und mit port 8008. Durch routing wird alles was auf port 8008 ankommt weitergeleitet auf port 1024. Das klappt auch soweit.

Wenn jedoch der Server eine neue Verbindung erstellen soll um die angeforderten Daten zu senden kommt nur : 

Java.not.ConnectException: Connection timed out ...
socket.connect(..)

obwohl der Receiver des anderen Programmes auf socket.accept steht und wartet das sich jemand verbindet.

Was genau meinst du mit Schwellenwert? Die 8008 hat mir mein Netzwerkadmin gegeben und mich gefragt auf welchen Port ich es gerne haben möchte... und die 1024 hab ich genommen weil mir die Zahl gefiel und ich irgendwo gelesen habe das 0 -1023 "belegt sind" <hüstel> 

Welche Informationen wären dir noch von Nutzen? Mit Netzwerken kenn ich mich zu meiner Schande leider nicht ganz so gut aus.

Aber unterm Strich läuft das ganze Programm durch und NUR das Aufbauen einer Verbindung zur Übermittlung der Ergebnisse klappt nicht.


----------



## Michael... (28. Nov 2011)

Thaflasher hat gesagt.:


> Ich benutze TCP und die Verbindung wird beendet sobald die Datenübertragung beendet ist. Anschließend baue ich eine neue Verbindung auf um eine Antwort zurück zu schicken.


Warum wird die ursprüngliche Verbindung nicht offen gehalten? Diese funktioniert offensichtlich.


----------



## TKausL (28. Nov 2011)

Michael... hat gesagt.:


> Warum wird die ursprüngliche Verbindung nicht offen gehalten? Diese funktioniert offensichtlich.



So sollte es auch bei Server/Client Anwendungen sein, da man von Clienten nicht verlangen kann, dass sie Ports anständig weiterleiten und freischalten.


----------



## Michael... (28. Nov 2011)

TKausL hat gesagt.:


> So sollte es auch bei Server/Client Anwendungen sein, da man von Clienten nicht verlangen kann, dass sie Ports anständig weiterleiten und freischalten.


so wie ich das verstanden habe soll doch eine kommunikation zwischen client und server stattfinden?


----------



## TKausL (29. Nov 2011)

Michael... hat gesagt.:


> so wie ich das verstanden habe soll doch eine kommunikation zwischen client und server stattfinden?



Ich habe dich doch nur bestätigt


----------



## Michael... (29. Nov 2011)

TKausL hat gesagt.:


> Ich habe dich doch nur bestätigt


sry, habe da wohl zu flüchtig drüber gelesen


----------



## irgendjemand (29. Nov 2011)

nun ... das ports 0-1023 belegt sind stimmt so nicht ... denn es gibt keinen port 0 ... sondern allerhöchstens 1 ... und genau da kommst du dann mit dieser zahl in konflikt ... denn offiziell sind ports 1-1024 als so genannte well-known-ports gedacht *zwar nicht immer belegt und oft blockiert ... macht aber nichts* ... darum sollte man immer einen port über 1024 wählen *genauer stimmt schon 1023 ... es gibt aber viele firewalls die mit den index-werten nicht ganz klar kommen und daher manchmal auch port 1024 als well-known ansehen*

der sinn hinter diesen well-known-ports ist lediglich das es innerhalb dieses bereiches bestimmte port-nummern und protokolle gibt die halt noch aus ur-zeiten stammen und sich daher "diesen platz gesichert haben"

besipeile sind :

20/TCP - FTP-data
21/TCP - FTP-control
22/TCP - SSH
23/TCP - TelNet
53/BOTH - DNS
67/UDP - DHCP-server
68/UDP - DHCP-client
80/TCP - HTTP
134/BOTH - 139/BOTH - alles möglich von Microsoft
443/TCP - HTTPS

um nur einige zu nennen ... *weitere fallen mir grad auch nicht ein ... müsste selbst nach lesen ... aber ich weis das da noch einiges kommt*

unter linux hat man weiterhin das problem das man als normaler user keinen dieser ports als server-socket öffnen kannst ... du unter linux also sowieso min 1025 wählen musst *auch wieder wieder wie oben beschrieben das problem mit der genauen darstellung -> vom system abhängig*

wenn dir dein netz-admin schon einen eigenen port 8008/TCP freigibt ... dann solltest du diesen auch verwenden ... erspart deinem admin unteranderem auch komplizierte route-settings und redirects ...


wo ich meinen vorrednern aber zustimmen muss : WAS ZUR HÖLLE MACHST DU DA ?

du baust von außen erfolgreich eine TCP-verbindung zum server aus und übermittelst diesem erfolgreich die daten ... und dann baust du die verbindung wieder ab ? und wartest dann auf dem client mit einem server-socket auf antwort ?

sorry ... aber aller spätestens an einem NAT-router mit firewall bei dem *selbst wenn du die range kennen würdest* nichts freigeschaltet ist ... dann ist da SCHLUSS !

eine TCP-verbindung wird so lange aufrecht erhalten bis du diese entweder selbst beendest ... oder sie auf grund eines netzwerkfehlers abreißt ...

also kannst du am anderen ende einfach mit einem READ so lange auf antwort vom server warten bis diese auch kommt ... genau so wie du am server auf die daten vom client wartest ...

das was du da vorhast ist irgendwie unlogisch , umständlich ... und auf grund von NAT-firewalls quasi zum scheitern verurteilt ...

nutze doch einfach die bestehende verbindung um auf die antwort zu warten ...

mal so die frage nebenbei weil es mich interessiert : warum baust du die stehende , scheinbar funktionierende verbindung wieder ab ? wenn das ganze auf dem server zu zeit-intensiv wird *5min für ne antwort oder so* ... dann arbeite mit nem service bei dem du dich anmelden und dich nach dem status deiner daten erkundigen kannst ... aber wenns n einfaches response ist was innerhalb von millisekunden vorliegt dann solltest du auch schon eine "normale" server-client-architektur verwenden ... und es bei der einen initialen verbindung belassen und alle daten über diese austauschen ...

denn wie gesagt : spästens an einem NAT-router ist bei dem was du vor hast ENDE ... da würden daten NIE ankommen ... oder was denkst du wie z.b. HTTP funktioniert ?

auch zu beachten : nur weil dein server auf 8008 *von außen betrachtet* läuft heißt es nicht das eine antwort auch von diesem als quell-port kommt ... *ist glaube ich nur bei UDP möglich* ... und selbst wenn müsstest du ja deinem user mitteilen welcher client-port offen sein müsste um überhaupt die chance zu haben daten zu empfangen ...

was auch komisch ist : wie meinst du das mit getInetAddress() ??
wenn du dort NICHT die quell-ip des clienten bekommst liegt es an dem netzwerk in dem der server steht und an der firewall die davor geschaltet ist
sowas nennt man symetrisches NAT ... also das dem client IM netz auch nur die IP der firewall als quell-ip bekannt ist ... nicht aber die wahre quell-ip wie sie an der firewall eintrifft ...

da solltest du vielleicht noch mal mit deinem netz-admin über grundlegende server-client architektur reden ... der sollte davon ahnung haben und wie genau die firewall / router / switch-server *oder was auch immer dazwischen hängt* arbeitet und die adresse umsetz ...


*sorry für den langen post ... aber du hast nun mal auch ne menge fehler in deiner denkweise*


----------



## Thaflasher (30. Nov 2011)

Der lange Post ist aber Gold wert, denn so langsam bekomm ich nen durchblick. :toll:

Habe öfters gelesen das ein Socket einzigartig ist, deswegen bin ich auch davon ausgegangen, dass ich entweder einen output- oder einen inputstream nehmen kann. Beides ist mir natürlich lieber 

Das einzige was mir jetzt noch ein Dorn im Auge ist, wie ich die Verbindung jetzt schließen soll. Der DataOutputStream schließt nicht mehr (da das schließen des OutputStreams leider auch den Socket schließt) und daher bekomme ich auch keine EOFException mehr, welche bisher meine Schleife unterbrochen hat.

Habe mir ein kleines Testprogramm geschrieben, da schicke ich am Ende der Übertragung einen "ENDE" String , was zwar funktioniert aber unsauber aussieht.

Was ist in dem Fall die gängige Praxis? Ein Timeout, ein "Ende" - zeichen oder das vorherige Übermitteln der Größe? ???:L

Nochmals vielen Dank für die Mühe

Grüße


----------



## TKausL (30. Nov 2011)

Einer von beiden (server oder Client) wird ja wohl wissen, wann er alles gesagt hat und nichts mehr wissen will. Mit dem Schließt du die Verbindung einfach 
	
	
	
	





```
con.close();
```
 Auf dem anderen wird dann sobald er aus dem Inputstream lesen will eine Exception ausgelöst.


----------



## Thaflasher (1. Dez 2011)

So jetzt habe ich meiner Meinung nach eine recht gute Lösung gefunden.

Ich übergebe beim senden vom Client an den Server den Socket, nachdem alles geschickt worde ist benutze ich:


```
socket.shutdownOutput();
```

Dies schließt nur den OutputStream aber dieser hat seinen Dienst schon erledigt. Der InputStream ist weiterhin offen. So bekommt mein Empfänger (der Server) mit das er nichts mehr zu erwarten hat und beendet nur den Empfang und nicht die gesamte Verbindung, das Programm läuft weiter.

Nachdem der Server geanwortet hat, schließt er auch gleich seinen DataOutputStream und der Socket ist geschlossen, die Verbindung abgebaut.

Da ich vorher schon mit setReuseAddress(true) klar gemacht habe das diese Addresse wieder benutzt werden soll, wird durch eine while(true)-Schleife gleich ein neuer Socket erstellt und der wartet wieder bis jemand eine Verbindung aufbaut.

Hab es mehrmals getestet -> läuft 

Evtl. kann jemand was mit der Info anfangen.

Danke an alle


----------



## irgendjemand (1. Dez 2011)

eine server-client architektur besteht in der regel aus 4 klassen

server-instanz -> listen/accept
verbindungs-thread -> bei verbindung eines clienten
client-instanz -> der client halt
data-thread -> der gegenpart zum verbindungs-thread des servers

das allgemeine schema ist folgendes


server-instanz

erstellt den serversocket und wartet dann in einem loop mit accept auf verbindungen
so bald sich ein client verbindet wird die angenommene verbindung in einen neuen thread gepackt und dieser gestartet ... dieser übernimmt die gesamte kommunikation mit dem client ...
für die instanz ist die verbindung jetzt hergestellt und weitergreicht ... fertig ... warten auf die nächste verbindung


verbindungs-thread

übernimmt die gesamte kommunikation mit dem client
er bekommt vom server den client-socket und eventuell andere daten *für broadcasts meist noch eine referenz auf die server-instanz selbst*
erst hier werden vom socket die streams geholt
mit Socket.getInputStream() bekommt man den stream auf dem daten vom client eintreffen
mit Socket.getOutputStream() bekommt man den stream auf dem daten zum client gesendet werden
wie du hier auf den trichter gekommen bist das du endweder NUR lesen oder NUR schreiben kannst weis ich nicht ... ist aber bei TCP/IP definitiv nicht so ...
in der regel läuft auch in diesem ein loop der die ganze zeit auf daten vom client wartet und bei erhalt auswertet ...
auch wird in diesem loop dierekt geantwortet ...
durch eine zusätzliche methode in dieser klasse ist es der server-instanz welche eine referenz auf die einzelnen threads hält möglich auch a-synchron daten zu senden ... *z.B. einen chat ... der server sendet die nachricht an alle sofort ... und muss nicht erst auf ein poll vom client warten nach dem motto : hast du neue daten für mich ?*
auch wird in dieser klasse das abbruch- und close-verhalten festgelegt
das abbruch-verhalten beschreibt die art und weise wie sich diese klasse verhalten soll wenn irgend ein fehler auftritt ... ob mit den daten die verarbeitet werden sollen ... mit der verbindung selbst ... oder oder oder ...
das close-verhalten beschreibt wie die verbindung "normal" abgebaut werden soll ...
in der regel gibt es ein key-word dafür ... z.B. quit oder exit welche ausgewertet und entsprechend mit abbau der verbindunge reagiert wird


client-instanz

ich denke hier ist nicht viel zu sagen ...
man sollte lediglich darauf achten das man alles was über eine I/O-verbindung läuft *egal ob lokal auf HDD oder über netzwerk* in eine extra thread-klasse auslagert und via referenzen eine kommunikation ermöglich
beliebtester fehler : innerhalb des EDT *EventDispatchThread - das teil was auf deine eingaben reagiert* lange aufwändige I/O-operationen ausführen welche zum "einfrieren" der GUI führen ... desshalb : alles was nicht dierekt die GUI selbst verändert in eigene threads auslagern


data-thread

der entsprechende gegenpart zum verbindungs-thread des servers
hier gibt es mehrere ansätze ... je nach dem was du brauchst
das wohl bekannteste ist das 2-thread-model
zur beschreibung
der data-thread ist eine thread-instanz welche von der client-instanz angestoßen wird ...
innerhalb dieses data-threads wird die verbindung hergestellt , die sockets geholt und alle handshakes vorgenommen ...
wenn du jetzt auf daten warten würdest hättest du das problem das du keine a-synchronen daten senden könntest ...
was wird hier also gemacht ?
innerhalb des data-thread wird ein weiterer thread gestartet welcher nur für das empfangen der daten vom jeweiligen gegenüber zuständig ist ...
der data-thread selbst dient lediglich zur überwachung der bindung und zum a-synchronen senden von daten ... das empfangen wird komplette vom untergeordneten receiver-thread durchgeführt
das ist natürlich nur eine variante ... aber eine welche fast immer zum einsatz kommt
es gibt auch noch varianten in denen nur dieser eine data-thread genutzt wird ...
andere wiederum starten bis zu 5 oder 10 child-threads um mehrere verbindungen gleichzeitig zu bedienen ...
du siehst : bei der gestaltung kommt es auf die anforderungen an ....

und das alles kannst du mit EINEM TCP/IP-socket umsetzen ... du musst die verbindung nur offen halten und auf beiden seiten auf dein key-word reagieren um die verbindung richtig abzubauen ...
und natürlich musst du im fehlerfall auch entsprechend mit abbruch-anweisungen reagieren

was passiert wenn zwischen dem senden der daten vom client zum server und der antwort mehr zeit benötigt wird

an sich erstmal nichts außer eine wartezeit
dadurch das der client schön in threads aufgeteilt ist läuft er normal weiter und wartet halt einfach bis eine antwort kommt ...
im server sieht es dagegen etwas komplizierter aus
wenn man den verbindungs-thread des servers als eine 1-thread config auslegt *wie ich beschrieben habe* kann dieser immer nur einen befehl gelichzeitig abarbeiten ... was durch zu lange timeouts zum verwerfen von daten im empfangs-puffer führen kann
abhilfe schaffen hier weitere threads ...
diese sollten jedoch nur dort eingesetzt werden wo man weis das die entsprechende anweisung mehr zeit benötigt ... da natürlich jeder weitere thread den server belastet ...
normalerweise braucht man sowas nur bei großen datenbanken und aufwändigen I/O operationen ... für die "einfache" ausführung "normaler" kommandos vergehen in der regel nur wenige millisekunden was bei einer guten verbindung dazu führt das der client die komplette antwort innerhalb ein bis zwei sekunden hat ... *wobei das schon echt ne ganze menge daten wären*


die wohl einfachste umsetzung für eine server-multiclient umsetzung findet sich auf der seite

Kaffee & Kuchen - Datenbank-Anbindung mit JDBC

anhand eines kleinen chat systems ...

! ACHTUNG ! einiges in diesem tutorial ist veraltet / deprecated ... der compiler weist an den entsprechenden stellen darauf hin !

als grundlage ist es aber gut geeignet ...

hoffe ich konnte dir jetzt irgendwie weiterhelfen


----------

