Langsame Socket-Verbindung übers Internet

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
py_fan_berlin
User
Beiträge: 13
Registriert: Dienstag 7. September 2010, 21:00

Hallo, ich habe wahrscheinlich ein Verständnißproblem zum Thema Sockets:

Ich versuche mit dem Standard Beispielen echo_server und echo_client eine "schnelle" Verbindung aufzubauen.

Server:

Code: Alles auswählen

import socket

HOST = ''                 # Symbolic name meaning all available interfaces
PORT = 8080              # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr

while 1:
    data = conn.recv(1024)
    print (data)
    if not data: break
    conn.send(data)
    
conn.close()
Client:
# Echo client program
import socket

HOST = 'euve11542.vserver.de' # The remote host
#HOST = '127.0.0.1' # lokale Maschine
PORT = 8080 # The same port as used by the server

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

for i in range(0,10000):
    s.send('Hello, world'+ str(i))
    data = s.recv(1024)
    print ('Received', data)
s.close()
Wenn das auf meinem Mac lokal läuft, dann sind die 10000 Aufrufe in ca. 2 Sekunden gelaufen.
Wenn ich das übers Internet (Server im Internet) laufen lasse, dann dauern die 10000 Aufrufe eine Ehhhhwigkeit,
ich breche das dann besser ab, es gehen so ca. 20-30 Aufrufe pro Sekunde durch.

Gibt es eine Möglichkeit das schneller zu machen ????

Es liegt offensichtlich nicht an der Leitung oder den beteiligten Rechnern/Routern etc., da
ich folgende Tests bereits gemacht habe:

Nur schreiben vom Client und Empfangen vom Server (Mac zuHause und Server im Internet und umgekehrt )
geht ebenfalls alles ratzt fatz.

Sobald jedoch der Client schreibt und liest, wirds so langsam wie oben beschrieben.
Es sieht so aus, als ob beim Schreiben und Lesen auf dem Client die Verbindung jedesmal neu aufgebaut wird.
Das heist die Verbindung bleibt nicht permanent offen.

Ich habe exakt die gleichen Ergebnisse mit Lua !!!

Was kann ich tun ??? Jede Hilfe/Anregung ist willkommen.
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

py_fan_berlin hat geschrieben:Nur schreiben vom Client und Empfangen vom Server (Mac zuHause und Server im Internet und umgekehrt )
geht ebenfalls alles ratzt fatz.

Sobald jedoch der Client schreibt und liest, wirds so langsam wie oben beschrieben.
Es sieht so aus, als ob beim Schreiben und Lesen auf dem Client die Verbindung jedesmal neu aufgebaut wird.
Das heist die Verbindung bleibt nicht permanent offen.
So ist das halt, dein Upstream ist halt nicht schneller :-) Der Datendurchsatz wird aber meist größer, wenn man mehr Daten auf einmal schickt - in dem Beispiel werden ja dauernd Pakete geschickt, die nur zu einem kleinen Teil gefüllt werden. Man könnte in der gleichen Zeit viel mehr Daten verschicken (natürlich nur gleichviele Pakete), wenn man mehr in ein Paket reinpackt.

(Nur nebenbei: Ein Frage- bzw. Ausrufezeichen genügt meistens.)
Benutzeravatar
py_fan_berlin
User
Beiträge: 13
Registriert: Dienstag 7. September 2010, 21:00

Nein, das liegt nicht am UpStream.

ich habe ja geschrieben, wenn ich nur in eine Richtung schreibe (z.B. von meinem Mac zum Server, also mit langsamem Upstream)
geht das sehr schnell !!!

Ich habe auch eine Konstellation mit 3 Programmen probiert:

1. auf meinem Mac, nur schreiben zum Server (Port 8080)
2. Auf dem Server im Internet (lesen und anworten) (port 8080 und 8081)
3. auf meinem Mac, nur Lesen (8081)

Dann geht das ganz auch fix (in wenigen Sekunden)

Es liegt also nicht am Datendurchsatz der DSL-Verbindung.
BlackJack

@py_fan_berlin: Wenn es das gleiche Problem bei Lua gibt, dann ist das vielleicht eher ein Problem mit dem Netzwerk beziehungsweise dessen Konfiguration!?

Oder kann es vielleicht sein, dass nicht gleich gesendet wird, sondern erst ein Timeout abgewartet wird, bis eine einzelne Nachricht rausgeht? Hast Du Dir den Verkehr schon mal "live" angeschaut? Zum Beispiel mit Wireshark.
Benutzeravatar
py_fan_berlin
User
Beiträge: 13
Registriert: Dienstag 7. September 2010, 21:00

@Moderator

nein, das habe ich mir noch nicht mit Wireshark angeschaut (ich bin auch kein Netzwerkspezialist).

Wenn ich auf dem Server pro Aufruf die Verbindung explizit öffne und schliesse komme ich genau zu dem Zeitverhalten.

Nach langem googeln habe ich in Lua den Hinweis gefunden, das nicht garantiert ist, dass die Socketverbindung
offen gehalten wird. Wenn der Client schreibt und anschliessend liest schein genau das der Fall zu sein und die
Socket-Verbindung muss neu aufgebaut werden.

Ein Freund von mir hat das gleiche Phänomen in Java, lokal alles super flott, über einen Router (DSL oder Wlan)
genau so langsam.

Wenn du einen Server im Internet hast, kannst du die beiden Scripte ja mal ausprobieren und mal selber testen.
Mir schein das nicht an der jeweiligen Umgebung zu liegen.

Ach ja, das gleiche Zeitverhalten ergibt sich übrigens auch mit einem XML-RPC, da hier ebenfalls auf einem Port
geschrieben und gelesen wird.

Deshalb bin ich ja auch erst auf Sockets ausgewichen und habe nun das gleiche Phänomen, nur dass ich es jetzt
besser zerlegen konnte.
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

py_fan_berlin hat geschrieben: (ich bin auch kein Netzwerkspezialist)
Aber du bist dir sicher, dass es nicht am Netzwerk liegt... erstaunlich, sowas zu wissen, ohne Kenntnis davon zu haben...

Ich habs nicht ganz verstanden: Hast du auch mal Client-nur-schreiben und Server-nur-lesen ausprobiert? Und das läuft genauso schnell wie das Selbe andersrum?
Wenn ich auf dem Server pro Aufruf die Verbindung explizit öffne und schliesse komme ich genau zu dem Zeitverhalten.

Nach langem googeln habe ich in Lua den Hinweis gefunden, das nicht garantiert ist, dass die Socketverbindung
offen gehalten wird. Wenn der Client schreibt und anschliessend liest schein genau das der Fall zu sein und die
Socket-Verbindung muss neu aufgebaut werden.
(Achtung Halbwissen meinerseits!) Die Verbindung wird dann aufgebaut, wenn du sie aufbaust, und dann beendet, wenn du sie beendest. Es gibt zwar Timeouts bei TCP-Connections, die sind aber irrelevant für dein Problem (die gehen afaik bei 30 Sekunden los).
Ein Freund von mir hat das gleiche Phänomen in Java, lokal alles super flott, über einen Router (DSL oder Wlan)
genau so langsam.

Wenn du einen Server im Internet hast, kannst du die beiden Scripte ja mal ausprobieren und mal selber testen.
Mir schein das nicht an der jeweiligen Umgebung zu liegen.
Ich hab mal genau das selbe Setup ausprobiert und habe natürlich das selbe Verhalten (DSL -> vServer). Zwischen zwei vServern, deren Leitung sauber konfiguriert und entsprechend dick ist, geht es natürlich viel schneller.
Ach ja, das gleiche Zeitverhalten ergibt sich übrigens auch mit einem XML-RPC, da hier ebenfalls auf einem Port
geschrieben und gelesen wird.

Deshalb bin ich ja auch erst auf Sockets ausgewichen und habe nun das gleiche Phänomen, nur dass ich es jetzt
besser zerlegen konnte.
XML-RPC läuft auch über Sockets (zumindest auf UNIX). Und alles, was du mit dem Socket machst, läuft letzendlich über eine TCP-Verbindung. XML-RPC ist auf einer höheren Schicht als Sockets, genauso wie HTTP, FTP, Torrent, ... es spielt für die Geschwindigkeit der TCP-Verbindungen keine Rolle, welches Protokoll du darüber sprichst.
Benutzeravatar
py_fan_berlin
User
Beiträge: 13
Registriert: Dienstag 7. September 2010, 21:00

O.K.

hier der "Talker", auf meinem Mac:

Code: Alles auswählen

# -*- coding: utf-8 -*-
# talker
import socket

talk_HOST = 'euve11542.vserver.de'
#talk_HOST = '127.0.0.1'

talk_PORT = 8080

talk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
talk.connect((talk_HOST, talk_PORT))

for i in range(1000):
    talk.send(str(i)+"---1234567890123456789012345678901234567890"+"\n")
    print (i)

talk.close()


Hier der "Listener", auf meinem Mac:

Code: Alles auswählen

# -*- coding: utf-8 -*-
# listener
import socket

listen_HOST = ''
listen_PORT = 8081

listen_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listen_s.bind((listen_HOST, listen_PORT))
listen_s.listen(1)

listen, addr = listen_s.accept()
print 'Connected by Listener', addr

while 1:
    data = listen.recv(1024)

    if not data: break

    print (data)
    
listen.close()

Und hier der "Listener_Talker", im Internet:

Code: Alles auswählen

# -*- coding: utf-8 -*-
# server listen and talk
import socket

listen_HOST = ''
listen_PORT = 8080

talk_HOST = 'marvin-tec.dyndns-ip.com' # meine dyndns für die Antwort
#talk_HOST = '127.0.0.1' # lokale Maschine
talk_PORT = 8081

listen_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listen_s.bind((listen_HOST, listen_PORT))
listen_s.listen(1)

listen, addr = listen_s.accept()
print 'Connected by Listener', addr

talk_connection = False

while 1:
    data = listen.recv(1024)
    print (data)

    if not data: break

    elif talk_connection == False:
        talk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)            
        talk.connect((talk_HOST, talk_PORT))
        talk_connection = True
        print 'Connected by Talker'

    talk.send(data)
    
listen.close()
talk.close()
Mit dieser Konfiguration werden 1000 Nachrichten innerhalb einer Sekunde
vom Talker (mein Mac) zum Listener_Talker (Internet) gesendet und
von dort an den Listener (mein Mac) gesendet.
JonasR
User
Beiträge: 251
Registriert: Mittwoch 12. Mai 2010, 13:59

Hast du die entsprechenden Ports in deiner Firewall bzw deinem Router auf gemacht?
Wenn du von deinem Mac auf deinen Server schreiben kannst aber nicht umgekehrt ist es bestimmt das angesprochene Problem... Solltest aber trotzdem mal mit WireShark rüber schauen ;)

Edit: Upsala ich habe eine Leiche ausgegraben?!?! :-/
Antworten