Ich bin immer noch bei meinem online spiel. Ich habe das problem, dass ich meinen Server nicht völlig überlasten will und die ganze zeit einfach nur anfragen senden will. Ich habe mir überlegt, dass der Server dem client mitteilen will, wenn sich etwas verändert. Wenn sich zum beispiel ein Monster bewegt.
Aber dann hätte ich das problem, dass ich dem server dann nichts gleichzeitig senden kann, da ich wenn ich was sende, ja auch ein ergebnis bekomme. Wenn ich also auf events warte und gleichzeitig nach zb. meinem leben frage, geht das ja nicht.
Was soll ich also tun. Soll ich einen 2. port aufmachen, der eine für die events, der andere für den rest oder was?
Wie würdet ihr das lösen?
Mehrere Ports öffnen?
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo INFACT!
Ich kann mich nicht mehr erinnern, welche Art von Kommunikation du bei deinem Spiel verwendest. Also ist folgende Strategie vielleicht nicht die richtige für dich.
Du könntest auf beiden Seiten mit Threads arbeiten -- musst du sogar. Jede Anfrage des Clients an den Server, wird an einen Thread weitergereicht. Im Idealfall hälst du genug Threads am Leben, um nicht ständig neue Threads erstellen zu müssen.
Weiters kannst du mit einem Timeout arbeiten. Wer sagt denn, dass eine Anfrage an einen Server "sofort" beantwortet werden muss. Lass die Anfrage so lange in der Luft hängen, bis du eine Antwort zur Verfügung hast, die es wert ist zurück gesendet zu werden.
Die Frage auf ``get_new_positions(client_id=123456789)`` z.B. könnte so lange mit der Antwort warten, bis es einen neuen Status (neue Positionen oder was auch immer) für den angegebenen Client gibt.
Ein Timeout auf Client- und Serverebene verhindert, dass zu lange blockiert wird. Nach einem Timeout wird vom Client einfach wieder die gleiche Frage gestellt -- bis irgendwann mal eine Antwort kommt, mit der der Client etwas anfangen kann.
Der Client stellt diese zeitintensiven Anfragen natürlich auch innerhalb eigener Threads, damit das Client-Programm nicht blockiert wird.
Der Server hat nur eine gewisse Anzahl an Threads zur Verfügung. Hier kann man dynamisch optimieren und je nach Client-Anzahl die Threadanzahl bis zu einem einstellbaren Wert erhöhen oder verringern.
Wenn man mehrere Prozessoren (oder Kerne) auf dem Server hat, dann kann man die Last zusätzlich noch auf ein paar Prozesse aufteilen. Der Server muss also threadsicher und prozesssicher programmiert werden.
So ein ähnliches System hatte ich mal für eine Bankomatkassen-Steuerung entwickelt. Und im Webbereich: CherryPy legt auch automatisch mehrere Threads an, die die Requests beantworten. Der Apache (mit mod_wsgi) startet mehrere CherryPy-Prozesse. Das kann man einstellen.
Mehr fällt mir im Moment nicht ein.
mfg
Gerold

Ich kann mich nicht mehr erinnern, welche Art von Kommunikation du bei deinem Spiel verwendest. Also ist folgende Strategie vielleicht nicht die richtige für dich.
Du könntest auf beiden Seiten mit Threads arbeiten -- musst du sogar. Jede Anfrage des Clients an den Server, wird an einen Thread weitergereicht. Im Idealfall hälst du genug Threads am Leben, um nicht ständig neue Threads erstellen zu müssen.
Weiters kannst du mit einem Timeout arbeiten. Wer sagt denn, dass eine Anfrage an einen Server "sofort" beantwortet werden muss. Lass die Anfrage so lange in der Luft hängen, bis du eine Antwort zur Verfügung hast, die es wert ist zurück gesendet zu werden.
Die Frage auf ``get_new_positions(client_id=123456789)`` z.B. könnte so lange mit der Antwort warten, bis es einen neuen Status (neue Positionen oder was auch immer) für den angegebenen Client gibt.
Ein Timeout auf Client- und Serverebene verhindert, dass zu lange blockiert wird. Nach einem Timeout wird vom Client einfach wieder die gleiche Frage gestellt -- bis irgendwann mal eine Antwort kommt, mit der der Client etwas anfangen kann.
Der Client stellt diese zeitintensiven Anfragen natürlich auch innerhalb eigener Threads, damit das Client-Programm nicht blockiert wird.
Der Server hat nur eine gewisse Anzahl an Threads zur Verfügung. Hier kann man dynamisch optimieren und je nach Client-Anzahl die Threadanzahl bis zu einem einstellbaren Wert erhöhen oder verringern.
Wenn man mehrere Prozessoren (oder Kerne) auf dem Server hat, dann kann man die Last zusätzlich noch auf ein paar Prozesse aufteilen. Der Server muss also threadsicher und prozesssicher programmiert werden.
So ein ähnliches System hatte ich mal für eine Bankomatkassen-Steuerung entwickelt. Und im Webbereich: CherryPy legt auch automatisch mehrere Threads an, die die Requests beantworten. Der Apache (mit mod_wsgi) startet mehrere CherryPy-Prozesse. Das kann man einstellen.
Mehr fällt mir im Moment nicht ein.
mfg
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Ja ich arbeite ja schon mit threads, auf beiden seiten.
Ich versuche mal mein problem besser zu beschreiben:
Mein Client löst ein event aus, er sendet neue coords an den server und wartet auf eine antwort. Wenn jetzt aber der Server ein event feststellt, kann der ja nicht ( auf dem selben port ) dem client das event schicken und auf eine antwort warten. Dann könnte es ja passieren, dass man als client, wenn man eine antwort auf das clientevent wartet, dann auf einmal das event vom server als antwort bekommt, oder nicht?
Hier nochmal zur verdeutlichung: Das kann doch nicht beides auf dem gleichen port funktionieren oder?
Ich versuche mal mein problem besser zu beschreiben:
Mein Client löst ein event aus, er sendet neue coords an den server und wartet auf eine antwort. Wenn jetzt aber der Server ein event feststellt, kann der ja nicht ( auf dem selben port ) dem client das event schicken und auf eine antwort warten. Dann könnte es ja passieren, dass man als client, wenn man eine antwort auf das clientevent wartet, dann auf einmal das event vom server als antwort bekommt, oder nicht?
Hier nochmal zur verdeutlichung:
Code: Alles auswählen
import socket
import thread
sock = socket.socket()
sock.connect(("localhost", 1234))
def waitForServerEvents():
while 1:
event = sock.recv(1024)
# parse event
def sendNewEvent():
while 1:
sock.send("laufe nach 123, 123")
ret = sock.recv(1024)
# vergleiche ret mit irgentwas
thread.start_new_thread(waitForServerEvents, tuple())
thread.start_new_thread(sendNewEvent, tuple())
while 1:
pass
# damit die threads nicht beendet werden
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
;-)
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo INFACT!
Öffne mehrere Verbindungen (zum gleichen Port), dann funktioniert das.
mfg
Gerold

Öffne mehrere Verbindungen (zum gleichen Port), dann funktioniert das.
mfg
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Was ist an 2 ports auszusetzen? Ist das gegen die rfcs?gerold hat geschrieben:Hallo INFACT!
Öffne mehrere Verbindungen (zum gleichen Port), dann funktioniert das.
mfg
Gerold
Edit: Es ist nähmlich einfacher 2 ports zu implementieren, aber ich kann es auch ändern...
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
;-)
Was meinst du mit drei anfragen? Ich kann nur maximal 2 haben. Wenn der server mir was mitteilen will und wenn ich dem server was mitteilen will. Wo nimmst du denn da die dritte her?mkesper hat geschrieben:Und was machst du bei drei Anfragen? Drei Ports? Und so weiter...
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
;-)
- veers
- User
- Beiträge: 1219
- Registriert: Mittwoch 28. Februar 2007, 20:01
- Wohnort: Zürich (CH)
- Kontaktdaten:
Sowohl TCP als auch UDP Verbindungen sind bidirektional. Dazu brauchst du nicht zwei Sockets, und wie mkesper schon sagte, du handelst dir damit vermutlich nur Ärger ein.
[url=http://29a.ch/]My Website - 29a.ch[/url]
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
Ja ich weiß. Ich habe ja gefragt, ob ich 2 ports oder 2 verbindungen öffnen soll...jbs hat geschrieben:port != Verbindung
Naja, zumindest so halb.
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
;-)
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo INFACT!INFACT hat geschrieben:Meinst du mit dem Modul socket?
Das Socket-Modul kümmert sich um das Versenden von Datenpaketen in bestimmten Größen und das Empfangen von Datenpaketen in bestimmten Größen. Es ist eine Low-Level-Schnittstelle um Daten von einem Programm/Rechner zu einem anderen zu schicken. Es kümmert sich nicht um die Datenstruktur.
Genau dafür gibt es High-Level-Schnittstellen wie z.B. XML-RPC (Beispiel), JSON-RPC, Pyro, usw.
Die einfachste Variante ist XML-RPC. Denn das ist bei den mit Python mitgelieferten Paketen schon mit dabei. Einfacher geht's nicht. Allerdings hat XML-RPC den Nachteil, dass es nicht performant ist, da es ziemlich viel Overhead mitschickt. Siehe: http://de.wikipedia.org/wiki/XML-RPC#Beispiele
Gleich einfach einzusetzen, aber mit viel weniger Overhead ist JSON-RPC. Siehe: http://en.wikipedia.org/wiki/JSON-RPC#Examples
Der Vorteil solcher High-Level-Schnittstellen ist, dass du dich nicht mehr um die Datenübertragung und um das Parsen der übertragenen Daten kümmern musst. Du kannst nämlich bei diesen High-Level-Schnittstellen direkt auf Funktionen verweisen.
Das heißt, dass du z.B. eine Funktion mit dem Namen "get_version_info" schreiben kannst und diese dann vom Client aus direkt aufrufen kannst. Die Rückgabe der aufgerufenen Funktion, die irgendwo auf einem Server ausgeführt wird, bekommst du auf dem Client zurück, als ob du die Funktion lokal aufgerufen hättest. Alles was dazwischen steckt (Netzwerkkommunikation, Parsen der übergebenen Parameter, usw.) ist damit nicht mehr wichtig.
Du kannst an diese Funktionen Parameter übergeben und bekommst auch Daten zurück. Alles was mit "normalen" Datenstrukturen wie Int, Str, List, Dict ist damit mehr als einfach handhabbar.
Wenn du also z.B. Koordinaten per Remote-Funktion übergibst und Irgendwelche Koordinaten zurück erwartest, dann bist du damit ziemlich gut bedient.
Wenn du nur ab und zu mal Binärdaten wie z.B. ein Bild vom Server holen musst -- ist es zwar langsamer als LowLevel-Datenübertragung, da es die Daten erst am Server in einen Text umwandelt und dann am Client wieder in die Binärdaten zurückwandelt, aber dafür ist es immer noch einfach handhabbar.
Sollte diese Art der Datenübertragung für manche Daten zu langsam werden, dann kann man (genau diesen Teil) einer anderen Datenübertragungsart übergeben. Z.B. direkt per Asyncore, asynchat oder vielleicht doch etwas höher per HTTP.
Und weil wir gerade dabei sind: HTTP ist wahrscheinlich gar nicht mal so schlecht für deine Zwecke geeignet.
Na dann lasse ich es mal wieder.
mfg
Gerold

PS: JSON-RPC: http://json-rpc.org/
PS2: fühlt sich etwas komisch an, aber vielleicht auch interessant für dich: http://github.com/niligulmohar/python-symmetric-jsonrpc
.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.