# Frage zu Serversocket-Beispiel aus der FAQ



## Guest (14. Jul 2008)

Ich hab hierzu mal ne Frage:

```
[...] 
// Server aufbauen 
ServerSocket server = new ServerSocket(1234); 
Socket s; 
while(true) { 
// Auf verbindung warten 
s = server.accept(); 
// kommunikation an einen nebenläufigen Thread abgeben 
ServerThread t = new ServerThread(s); 
t.start(); 
// und wieder auf neue Verbindungen warten 
}
```

Seh ich das richtig das jeder Client der sich hier verbindet auf dem Port 1234 geht?
Sprich bei 100 Clients alle über den selben Port gehen? Oder seh ich da was falsch? 
Weil ich benutz für mich im Moment für jeden Client nen eigenen Serversocket, und 
somit auch nen eigenen Port (zufällige eindeutige Zahl). Hab ich da was am Konzept 
verpasst? 

Thx schonmal


----------



## musiKk (14. Jul 2008)

Der Server horcht an Port 1234. Der Socket, der vom accept() zurueckgeliefert wird, laeuft aber ueber einen anderen Port. Der wird meines Wissens von der Netzwerkkomponente des Betriebssystems zugewiesen und kann daher nicht selbst beeinflusst werden (allerdings bin ich mir da nicht hundertprozentig sicher). Es reicht also ein ServerSocket.


----------



## Guest (14. Jul 2008)

Hm, na toll. 
Welche Nachteile oder Vorteile ergeben sich denn wenn ich pro Client einen ServerSocket (wär mein Ist-Zustand) hab?
Im Moment muss ich mir ziemlichen Stress machen mit den Sockets schliessen und die vergebenen Sockets 
überwachen etc, das wär ja schonmal ein Nachteil. Und ne schlechte Pingrate hab ich auch  Aber ich glaub das 
liegt nicht daran. 

Was wär denn da an Informationen noch entscheidungsfördernd?


----------



## Niki (14. Jul 2008)

Der Client muss ja wissen auf welchen Port er sich verbinden soll. Wie soll er das machen wenn du den Port per Zufall generierst? Du brauchst genau einen ServerSocket der Verbindungen immer am selben Port entgegen nimmt. Verbindet sich ein Client wird ein neuer Thread erzeugt, der die Anfragen vom Client verarbeitet. Dann wird wieder auf dem selben Port gelauscht.


----------



## musiKk (14. Jul 2008)

Die Nachteile hast du selbst aufgezaehlt, Vorteile fallen mir keine ein.


----------



## Guest (14. Jul 2008)

Also der Client weiss das schon ganz genau wo der sich hinverbinden soll, weil ich beim ersten accept den 
generierten  Port an den Client zurückwerfe, nen neuen ServerSocket mit der Portnummer aufmache, und der Client
connected sich dann auf der zugewiesenen Portnummer. ...

Ich ahne das ich da ganz grossen Schwachsinn gebaut hab :/ 

Aber dann versteh ich das nicht, jeder Client connected sich dann doch auf die 1234, dann läuft doch auf 
dem Server alles über den einen Port???

```
Socket socket = new Socket("127.0.0.1", 1234);
```
Auch wenn auf dem Server dann die Auszuführenden Operationen in einen eigenen Thread gekapselt sind
schiebt sich dann doch jeder client durch den einen Port, oder nicht? Wie bekommt der Client da mit das das
dann plötzlich und aus mir nicht nachzuvollziehbaren Gründen über ne andere Portnummer gehen soll?


----------



## musiKk (14. Jul 2008)

Anonymous hat gesagt.:
			
		

> Aber dann versteh ich das nicht, jeder Client connected sich dann doch auf die 1234, dann läuft doch auf
> dem Server alles über den einen Port???





			
				musiKk hat gesagt.:
			
		

> Der Socket, der vom accept() zurueckgeliefert wird, laeuft aber ueber einen anderen Port.


Mit accept() wird an einem Port gelauscht und blockiert. Dann verbindet sich ein Client. accept() baut eine Verbindung auf und liefert dir einen Socket darauf. Diese Verbindung geht ueber einen Port, den du nicht beeinflussen kannst, jedoch ueber einen anderen.


----------



## Gast (14. Jul 2008)

Uhhh, so langsam raff ichs glaub ich... 

Danke für die Hilfe, ich code das mal um, wenn ich Probleme haben sollte post ich wieder


----------



## tuxedo (14. Jul 2008)

Socketverbindungen sind nunmal so designed dass es einen Port für alle Clients gibt... Wo kämen wir denn hin wenn jede Webseite beim nächsten Klick unter einem anderen Port erreichbar wäre?

Sehe da keinen Nachteil. Das OS bzw. der TCP/IP Stack deckelt das schon entsprechend.

Wenn du dir irgendwelche Gedanken machen willst, dann eher wegen dem "pro verbundenen Client existiert ein Thread" ... Das ist, in anbetracht dessen dass die Port-Sache vom OS / TCP/IOP Stack gedeckelt wird,  (gigantisch viel) schlimmer als für jeden Client ein und denselben Port zu benutzen ... 

- Alex


----------



## Guest (15. Jul 2008)

Also ich hab das gestern abend mal angefangen umzubauen, es läuft zwar noch nicht, aber das ist ja nur eine Frage 
der Zeit  



			
				alex0801 hat gesagt.:
			
		

> Wenn du dir irgendwelche Gedanken machen willst, dann eher wegen dem "pro verbundenen Client existiert ein Thread" ... Das ist, in anbetracht dessen dass die Port-Sache vom OS / TCP/IOP Stack gedeckelt wird,  (gigantisch viel) schlimmer als für jeden Client ein und denselben Port zu benutzen ...



Wieso? Ich wüsst nicht wie ich das sonst realisieren soll was ich brauche, aber bin ganz Ohr 
Mein momentanes Konzept ist so:
Spieler meldet sich am Server an, bekommt ein eigenes InterfaceObject das 
1. alle Userabhängigen Daten speichert
2. das empfangen und senden von Daten von und zu dem Client regelt 
3. in einem eigenen Tread läuft.
Dadurch brauch ich nie Daten übers Netzwerk zu senden um auf den einen Client / Character in der Welt zu verweisen, 
sondern nur noch die zu verarbeitenden Befehle. Das das nur von dem einen User/Character sein kann ist dann eindeutig. 

Das macht je Spieler einen Thread (Je nach dem was der Spieler grad macht versende ich nur 2 Pakete je Sekunde),
einen Tread der die Spawns und Questsstarts/ende Checkt und je einen Tread für jeden intelligenten NPC. 
Joa, ich seh ein da kommt schon was zusammen... 

Wie würdst du das denn realisieren?


----------



## tuxedo (15. Jul 2008)

Problem war ja:

>> Der Client muss ja wissen auf welchen Port er sich verbinden soll. Wie soll er das machen wenn du den Port per Zufall generierst?

Und darauf bin ich ebenfalls eingegangen. Dass jeder Client ein Socketobjekt braucht ist (nahezu) selbstredend. Eine Socketverbindung hat immer zwei Endpunkte, einen auf Client und einen auf Serverseite. Das muss so sein und ist auch "gut" so.

Das was du da zusammengetextet hast:

>> Dadurch brauch ich nie Daten übers Netzwerk zu senden um auf den einen Client / Character in der Welt zu verweisen,
sondern nur noch die zu verarbeitenden Befehle.

Ist in sich etwas "seltsam" formuliert. Mehr wie "zu verarbeitende Befehle" will ja auch niemand senden. Wüsste jetzt auch nicht was da sonst noch dabei sein soll. Die Zuordnung, welcher Socket/Stream jetzt zu welchem Client gehört ist Sache der Serverlogik. Dafür gibts ja HashMaps und andere "Techniken" die man hierzu verwenden kann. Das hat aber nix mehr mit Socketprogrammierung an sich zu tun. 

Ich denke das ganze ist bei dir mittlerweile ein, sorry für den Ausdruck, verwuschteltes und verwachsenes System. Es mag funktionieren, aber du wirst vermutlich irgendwann schnell an die Grenzen stoßen (je nachdem wie groß das Ding werden soll und wieviele gleichzeitigen Clients unterstützt werden sollen)

So viele Threads sind nebenbei nicht förderlich. Je nachdem wieviele das Spiel spielen sollen/wollen, stellt das sogar eine direkte Limitierung dar.

Mit xSocket (noch etwas low-level) oder SIMON (etwas mehr high-level, auf dem Niveau von RMI, siehe meine Signatur) kannst du die Anzahl der für die KOmmunikation benötigten Threads drastisch reduzieren (eine Hand voll Threads für hunderte/tausende Clients), was bei vielen Spielern mehr performance bringen kann.

Vielleicht solltest du dir das mal anschauen. Und wie gesagt:

>> Seh ich das richtig das jeder Client der sich hier verbindet auf dem Port 1234 geht? Sprich bei 100 Clients alle über den selben Port gehen?

Ja das siehst du richtig, und ja das muss auch so sein. Und nein, das bringt keine Performance-Probleme mit sich.

Gruß
Alex


----------



## Guest (15. Jul 2008)

alex0801 hat gesagt.:
			
		

> Ich denke das ganze ist bei dir mittlerweile ein, sorry für den Ausdruck, verwuschteltes und verwachsenes System. Es mag funktionieren, aber du wirst vermutlich irgendwann schnell an die Grenzen stoßen (je nachdem wie groß das Ding werden soll und wieviele gleichzeitigen Clients unterstützt werden sollen)



1. Du denkst richtig, das sorry kannst du dir schenken 
2. riesig und tausende clients  Ist ein 2d-online-rpg (oder solls mal werden)

Aber zu dem verwurschtelt, ich denke das ich im grossen und ganzen bis auf ein paar Hacks recht ordentlich
strukturiert bin. Mit den uml's zu Server, Client und Karteneditor hab ich mein Wohnzimmer tapeziert. Sogar die 
Knackpunkte hab ich ordentlich im Code kommentiert. Ich wär jetzt eigentlich an die NPC's gegangen, aber 
das mit dem Netzwerk schieb ich dazwischen. 

Zu Simon: Als ich so im November rum hier im Forum gesucht hab wie ich das mit dem Netzwerkverkehr regeln
soll lief auch grad ein Post mit deinem Simon, ich hab das ganze dann auch mitverfolgt, wusst damit aber nicht so
recht was anzufangen, und hab mir dann auf Reflection und Socket was aufgebaut. Was auch bis jetzt einwandfrei
funktioniert, mal abgesehen von einem schlechten Ping (im WLan 250 - 350 ms). Das ganze mal Testweise auf
Simon umzubauen sollte aber kein Problem, nur Fleissarbeit sein, nur hab ich von Simon absolut keine Ahnung.
Zumindest jetzt noch nicht


----------



## tuxedo (15. Jul 2008)

Schau mal auf die Projektseite von SIMON. Da hast du ein kleines funktionierendes Beispiel das (fast) den ganzen Funktionsumfang erklärt. 

Seit November hat sich extrem viel getan. MIttlerweile läuft SIMON recht stabil und ist auch komplett auf NIO umgestellt. 

Die Latenzen die du da beschreibst sind wohl teilweise auf den Nagle-Algorithmus zurückzuführen. Den kann man abschalten, dann wirds besser. Aber bei mir warens, soweit ich mich erinnern kann, nur um 100..150ms die ich mit dem abschalten von Nagle auf nahezu 0 reduzieren konnte. D.h. bei dir ist da noch was anderes im argen was bremst (das WLAN kanns nicht sein. Hab über eine 200meter WLAN-Brücke eine Latenz von <2ms).

- Alex


----------



## Guest (15. Jul 2008)

Ja, ich hab auch so ne Ahnung an was das liegt :/ 

Ich hatt halt als ich damit angefangen hab von Netzwerk-Programmierung keine Ahnung, und hab mir halt was
zusammengebaut, das zwar super funktioniert, aber wohl nicht wirklich schnell ist. Im Prinzip hab ich in meinen
Paketen die ich verschicke den Klassennamen und Methodennamen als String und die Übergabeparameter als
Objekte, der Empfänger hat ne Liste mit allen schon fertig instanziierten Klassen, auf die frägt er den Klassennamen
mit equals ab und macht im true-Fall ein invoke auf die passende Methode mit den ÜbergabeParametern. 

Da sieht Simon für mich nach nem performanteren Weg aus  Da ich aber nicht weiss was aus dem Spiel mal wird
würden mich bei Simon vorher die Lizenzkosten für eine kommerzielle Nutzung interessieren.


----------



## tuxedo (15. Jul 2008)

GPL hat nix mit kommerziell/nicht kommerziell zu tun. Die GPL verbietet dir nicht, dein Programm zu verkaufen. Alles was die GPL vor schreibt ist, dass der Source offen gelegt werden muss.

Wenn dich das "hindert" SIMON zu benutzen, schreib mir mal ne PM ...

- Alex


----------



## Guest (15. Jul 2008)

Ok, muss mich nur erst registrieren hier, da komm ich aber erst morgen dazu. 

Danke an dieser Stelle nochmals an alle für eure Hilfe


----------



## Hollow (15. Jul 2008)

So, frisch registriert 

Wie ist das nun mit dieser GPL? Weil für mich hört sich das mit der GPL sogar gefährlich an. 
Wenn jeder den Quellcode von dem Spielclient, oder noch schlimmer, vom dem Server kennt, da ist doch jedem
ScriptKiddie Tür und Tor geöffnet, oder seh ich das falsch? 
Und wie will man das Urheberrecht an seinen Programmen sicherstellen? Der nächste zieht den Code einfach
in seine Eclipse und behauptet er wär von ihm. 
Oder noch besser, startet das Spiel im Debugger und Coded sich das on the Fly zurecht wie er's brauch.

Ich weiss nicht, das hört sich nicht so erstrebenswert an, oder?


----------



## tuxedo (15. Jul 2008)

Es gibt im Netz ausreichend Diskussionen zur GPL. Beide Lager (Gegner und Befürworter) sind stark vertreten. 

Viele große Firmen benutzen die GPL (so z.B. auch MySQL mit deren JDBC Treiber "Connector/J"). GPL hat den Vorteil, dass alle GPL Anhänger GPL-Code nahezu frei Nutzen können. Somit schottet sich GPL etwas von den Entwicklern propritärer Software, welche Angst um die vermeintliche Sicherheit des Systems haben ab.

Quellcode "geschlossen" zu halten hat nicht nur den Vorteil dass niemand rein schauen kann. Es hat auch den Nachteil dass niemand reinschauen kann und nachsehen kann ob die Sache auch tatsächlich "sicher" ist. 

Und klar: Auf der anderen Seite, gerade bei verteilten Onlinespielen, ist es äußerst verlockend mal in den Source zu schauen und irgendwas zu "ercheaten".

Aber lass dir gesagt sein: Auch bei closed-Source Projekten werden Cheats versucht (und das teilw. sogar erfolgreich). Weil findige Tüftler kriegen im nu das Protokoll raus und schleußen Pakete ein die nicht dahin gehören.

Der einzigste Weg sich vor solchen "Attacken" zu schützen ist eine saubere und gut durchdachte Implementierung.

Nun zurück zu deinem Anweundgsfall:

Den Server wirst du wohl eher nicht verkaufen wollen, nehm ich an?! Wenn du diesen nicht publizierst/vertreibst, dann darf dieser auch GPL nutzen (für nicht veröffentlichte Programme ist die GPL quasi wurscht).

Beim Client ist es anders. Den willst du ja verteilen (kostenpflichtig?). Wenn du aber sauber programmierst und die ganze Logik im Server abwickelst (was du wirklich durchgängig tun solltest) und eingehende Daten immer schon validierst, dann kann sich jemand mit dem Source vom Client auf den Kopf stellen und er kriegt nix "gecheatet". Das ist ähnlich wie mit eine, Browser:

Der Webserver steht irgendwo und wurde nicht publiziert. Du gibst den Quellcode für deinen browser frei. Und selbst wenn jetzt jemand anderes daher kommt und anhand deines browser-Sources einen eigenen Browser baut hat er nix gewonnen: Der Server bietet nach wie vor die gleiche Funktion an.

Wenn du ein kommerzielles Projekt vor hast, dann würde ich eher nicht den Client verkaufen und das spielen kostenlos machen, sondern eher den client "verschenken" und das spielen kostenpflichtig machen.

Selbst wenn du eine propritäre Lizenz von SIMON erwirbst und deinen Client "closed source" machst: Decompiler extrahieren dir einen fast 1:1 den original identischen Sourcecode... Da hilft nur ein "Obfuscator" der den Sourcecode unleserlich macht. Aber auch das hilft nix gegen eingriffe/änderungen in den Client. 

So oder so liegt die Sicherheit des Systems voll beim Server, und nicht beim Client. Ob mit GPL oder ohne. 

So, aber jetzt zur PM ..


gruß
Alex


----------

