Mehrere Ports öffnen?

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

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?
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
Benutzeravatar
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
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

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:

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
Das kann doch nicht beides auf dem gleichen port funktionieren oder?
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
Benutzeravatar
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
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

gerold hat geschrieben:Hallo INFACT!

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

mfg
Gerold
:-)
Was ist an 2 ports auszusetzen? Ist das gegen die rfcs?
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]
;-)
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Und was machst du bei drei Anfragen? Drei Ports? Und so weiter...
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

mkesper hat geschrieben:Und was machst du bei drei Anfragen? Drei Ports? Und so weiter...
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?
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Okay, sorry. Trotzdem ist es anscheinend möglich, das über einen einzigen Port zu regeln. Ist einfacher, falls es mal durch irgendwelche Firewalls geroutet werden muss.
Benutzeravatar
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
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

Ja, aber ich kann nicht 2 anfragen gleichzeitg über eine verbindung laufen lassen.
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

port != Verbindung

Naja, zumindest so halb.
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

jbs hat geschrieben:port != Verbindung

Naja, zumindest so halb.
Ja ich weiß. Ich habe ja gefragt, ob ich 2 ports oder 2 verbindungen öffnen soll...
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wieso arbeitest Du eigentlich so low-level? Gibts dafür nen Grund? Gibt ja nette Bibliotheken, die einem da das Leben einfacher machen...
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

Meinst du mit dem Modul socket?
Ich kenne mich damit halt am besten aus.
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Naja, wieso nicht xmlrpc o.ä.?
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

INFACT hat geschrieben:Meinst du mit dem Modul socket?
Hallo INFACT!

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.
Antworten