Seite 1 von 1
Python zu langsam? =(
Verfasst: Sonntag 11. September 2005, 21:32
von jihi
Ich hab folgendes Problem:
Hab ein Programm geschrieben, was sich zwischen ein Spiel und den Server schaltet.
Code: Alles auswählen
# -*- coding: cp1252 -*-
from socket import *
# Set the socket parameters
addrc = ("0.0.0.0",23072)
addrs=("84.254.75.8",23110)
hostc="0.0.0.0"
portcl=23072
portcs=23083
hosts="84.254.75.8"
portsl=23082
portss=23110
buf = 1024
# Socket zuständig für Server Verbindung
socks = socket(AF_INET,SOCK_DGRAM)
socks.setblocking(0)
socks.bind(("0.0.0.0",portsl))
# Socket zuständig für Client Verbindung
sockc = socket(AF_INET,SOCK_DGRAM)
sockc.setblocking(0)
sockc.bind((hostc,portcl))
count=0
a=0
## Schleife ################################
while 1:
datas=0
datac=0
## Daten von Client an server
try:
datac,(hostc,portcs)=sockc.recvfrom(buf)
except:pass
if datac:
## print "CtS:"+datac
socks.sendto(datac,(hosts,portss))
count =0
##Daten von Server an Client
try:
datas=socks.recv(buf)
except:pass
if datas:
## print "StC:"+datas
sockc.sendto(datas,(hostc,portcs))
count+=1
if count>100000:break
if count%10000==0:print count,
# Close socket
socks.close()
sockc.close()
Funktioniert auch wunderprächtig, nur lastet Python dann den Computer zu 70% aus, was somit das Spiel völlig ausbremst
kann man das irgendwie beschleunigen ?
Oder ist das einfach die Grenze von Python?
(Ich bin mir bewusst, dass Python nicht mit C++, oder Asembler zu vergleichen ist, besonders was Geschwindigkeit angeht. War auch mehr einfach ein Versuch mit Sockets. Aber vielleicht gehts ja doch =)
Edit XT@ngel: Code in Python Tags
Verfasst: Montag 12. September 2005, 04:12
von mitsuhiko
Probier mal folgendes:
Lastet deinen Computer perfekt aus
Zu deinem Problem: Probiers mal mit Threads anstatt einer einfachen While Schleife. Das sollte dann schon flüssiger laufen.
Verfasst: Montag 12. September 2005, 08:38
von rayo
Hi
Schau dir mal das modul select an. Da kannst du warten bis der Socket Daten zum lesen oder schreiben hat. Somit sollte die last drastisch sinken.
Code: Alles auswählen
readyForRead, readyForWrite, error = select( [socks,sockc], [socks,sockc], [socks,sockc])
for readingSocket in readForRead:
print readingSocket.recvfrom(buf)
for writingSocket in readForWrite:
print writingSocket.sendto(datac,(hosts,portss))
Gruss
Verfasst: Dienstag 13. September 2005, 20:17
von jihi
Das mit den Thread/Threading hab ich leider noch garnicht verstanden
Aber:
Hab ich das jetzt richtig verstanden
select wartet, bis Daten ankommen, und gibt dann die Socken zurück, wo Daten vorhanden sind, und wo keine sind, die nicht?
Und wenn ich zwischendurch selber Packets senden möchte, dann muss ich warten, bis bei einem der sockets Daten angekommen sind, oder der Timeout abgelaufen ist?
Ist ja cool
[wenns denn so ist]
[habs noch nicht versuchen können
]
Verfasst: Dienstag 13. September 2005, 21:03
von ProgChild
jihi hat geschrieben:Und wenn ich zwischendurch selber Packets senden möchte, dann muss ich warten, bis bei einem der sockets Daten angekommen sind, oder der Timeout abgelaufen ist?
Nein. Select sagt dir auch, welche Sockets zum schreiben bereit sind, wenn du etwas senden möchtest.
Sonst hast du das schon verstanden...
Verfasst: Dienstag 13. September 2005, 21:57
von jihi
aber wann ist denn ein Socket bereit zum Senden ?
Eigentlich doch immer oder????
Also wenn ich jetzt nicht grade ein Riesen Packet gesendet habe.
Also ist doch der Nutzen von select eigentlich zu Nichte oder?
Verfasst: Dienstag 13. September 2005, 22:48
von rayo
wenn du nun z.B. 100kb Daten senden willst, ist er eine Zeit lang nicht bereit zum senden, aber die meiste zeit ist er das eigentlich schon.
Ich würde es über Queues machen, wenn der socket bereit ist zum schreiben holt er die nächste nachricht der queue und schickt diese.
Die Queue ist auch Thread-Safe (sprich aus mehreren Threads ansprechbar ohne probleme).
Code: Alles auswählen
import Queue
writeQueue = Queue.Queue()
while 1:
readyForRead, readyForWrite, error = select( [socks,sockc], [socks,sockc], [socks,sockc])
for readingSocket in readForRead:
print readingSocket.recvfrom(buf)
for writingSocket in readForWrite:
try:
data = writeQueue.get(False)
print writingSocket.sendto(data,(hosts,portss))
except Queue.Empty:
#keine Daten in der Queue
pass
Jetzt kannst du irgendwo in einem anderen Thread z.b. writeQueue.put('hallo welt') schreiben und es wird sobald der socket bereit ist abgeschickt.
Gruss
Verfasst: Dienstag 13. September 2005, 22:55
von jihi
Vielen Dank erstmal =)
hast mir sehr geholfen, werds gleich mal testen
Verfasst: Mittwoch 14. September 2005, 08:42
von jihi
Leider funktioniert das mit select irgendwie nicht: Obwohl packages ankommen müssten, geht er nicht weiter
Oder funktioniert das ganze nur mit TCP, weil ich benutze UDP
Code: Alles auswählen
# -*- coding: cp1252 -*-
from socket import *
from select import *
# Set the socket parameters
addrc = ("0.0.0.0",23072)
addrs=("84.254.75.8",23110)
hostc="0.0.0.0"
portcl=23072
portcs=23083
hosts="84.254.75.8"
portsl=23082
portss=23110
buf = 1024
# Socket zuständig für Server Verbindung
socks = socket(AF_INET,SOCK_DGRAM)
##socks.setblocking(0)
socks.bind(("0.0.0.0",portsl))
# Socket zuständig für Client Verbindung
sockc = socket(AF_INET,SOCK_DGRAM)
##sockc.setblocking(0)
sockc.bind((hostc,portcl))
count=0
a=0
# Receive messages
while 1:
## select soll nur weiter gehn, wenn Daten ankommen, nicht wenn es bereit zum Senden ist?!
readyForRead, readyForWrite, error = select([socks,sockc],[], [], 5)
if readyForRead ==[]: break
for readingSocket in readyForRead:
if readingSocket == socks:
sockc.sendto(readingSocket.recv(buf),(hostc,portcs))
if readingSocket == sockc:
datac,(hostc,portcs)=sockc.recvfrom(buf)
sockc.sendto(datac,(hosts,portss))
# Close socket
socks.close()
sockc.close()
Edit (Leonidas): Code zum zweiten mal in Python-Tags gesetzt (zum ersten mal von XT@ngel), beim nächsten mal selber machen, ok?
Verfasst: Mittwoch 14. September 2005, 08:51
von rayo
Hi
eigentlich alles ok, nur das ist irgendwie fehl am platz:
if readyForRead ==[]: break
wenn 5s nach programmstart keine daten da sind, bricht er die ganze schleife ab (timeout bei select hast du ja auf 5 gesetzt)
Bist du sicher das auch Daten an den Ports auf UDP ankommen? Also hatte das vor dem Wechsel auf select funktioniert??
Gruss
Verfasst: Mittwoch 14. September 2005, 10:32
von jihi
Ja, vorher hat das einwandfrei funktioniert.
Irgendwie komisch, funktioniert das vielleicht in WinME nicht?
Das
stimmt schon, ist die einfachste Möglichkeit, das Programm mit socket.close() zu beenden.
Oder gibt es da noch was besseres um schleifen zu verlassen(ich glaub da war grad so ein Thread dazu?! mal gucken)