UDP-Problem

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Montag 9. Juni 2008, 07:40

Hallo!

Ich hab ein kleines Problem. Ich will in regelmäßigen Abständen eine "größere" Datenmenge (d.h. ca. 200kb) über das UDP-Protokoll versenden. Dazu muss ich die Daten in einzelne Pakete aufteilen. Wenn ich nun in direkter Abfolge mehrere Pakete verschicke empfange ich nicht alle. Solange ich über den localhost schicke, sollten ja auch keine Pakete unterwegs verloren gehen. Ich nehme an das es einen Empfangspuffer gibt, der dann vollgeschrieben wird und mit recv nur die Daten entnommen werden können, die in dem Puffer im Moment enthalten sind. Ich weiß jedoch nicht wie groß dieser Puffer ist, geschweige denn wie man ihn verändern kann, noch bin ich mir sicher ,dass es daran liegt.
Ich habe ein Beispielprogramm geschrieben um das Problem zu verdeutlichen:

Hier ist das Client-Programm:

Code: Alles auswählen

import socket

SERVER_ADDRESS = '127.0.0.1'
SERVER_PORT = 50007
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)

try:
        while True:
                for i in range(20):
                        client.sendto('x'*1024,(SERVER_ADDRESS, SERVER_PORT))
                        print 'sending  #',i
                raw_input('...')
finally:
        client.close()
und hier das Server-Programm:

Code: Alles auswählen

import socket

PORT = 50007
BUFLEN = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
server.bind(('127.0.0.1', PORT))
i=0
try:
        raw_input('Pakete abrufen...')
        while True:
                message = server.recv(BUFLEN)
                print 'Received packet',len(message),i
                i+=1
finally:
        server.close()
Wenn ich den Server starte, dann den Client und dann die Pakete abrufe, empfängt der Server bei mir nur 8 der 20 gesendeten Pakete.

Danke im Voraus!
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Montag 9. Juni 2008, 08:17

Bist du dir sicher, dass du das direkt über Sockets machen willst und nicht über nen ordentliches Protokoll? :o
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Montag 9. Juni 2008, 08:51

UDP ist doch ein ordentliches Protokoll :D
Es soll so wenig wie möglich Traffic entstehen, da es für die Anwendung (Maschinensteuerung) wichtig ist,
dass ein anderes Signal welches aller 3ms gesendet werden muss, so wenig wie möglich behindert wird.

Ich glaub ich hab auch schon die Lösung gefunden. Das Problem leigt tatsächlich beim empfangen. Mit

Code: Alles auswählen

print server.getsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF)
kann ich mit den Gesamt-Empfangspuffer anzeigen lassen.
Der liegt bei mir bei 8192.
Wenn ich ihn auf 8192*2 setze, werden entsprechend doppelt so viele Pakete abgerufen.

Code: Alles auswählen

server.setsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF,8192*2)
Um die 200kb zu empfangen reicht es also wenn ich die Puffergröße auf 210000bytes anheb.
Dann kann die gesamte Nachricht abgerufen werden. Bis zur nächsten Nachricht vergeht genug Zeit um den Puffer komplett zu leeren.
Das ist zwar allgemein nicht sehr elegant, aber für die Anwendung reichts.
Wenn jemand noch ne allgemein bessere Lösung einfällt ohne TCP zu nutzen kann er sie ja posten.
Ich frag mich wie das bei Videoübertragung über UDP funktioniert?
Dann gibt es vmtl. einen Rückkanal.
BlackJack

Montag 9. Juni 2008, 09:59

Entweder gibt es eine Möglichkeit der Rückmeldung welche Pakete anscheinend ausgefallen sind, oder die verloren gegangenen Pakete werden einfach ignoriert.

Bei Deinen Beispielen da oben kommen bei mir auf dem Rechner lokal getestet übrigens 0% der Pakete beim Server an. :shock:
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Montag 9. Juni 2008, 10:28

Misteriös... :?
Vielleicht hast du etwas an der Reihenfolge falsch gemacht...

1. Server starten
2. Client starten
3. erst jetzt Enter bei Server drücken

(Ich hab das mit dem verspäteten Abrufen gemacht, da das Problem sonst nur auftritt wenn der Server langsamer abruft als der Client sendet.
Und das passiert wenn alles auf dem selben Rechner läuft nur gelegentlich, auf unterschiedlichen Rechnern ist es halt hardwareabhängig.)

Wenn das nicht der Grund ist könnte es daran liegen, dass ein Zeitlimit bei dir gesetzt ist, welches nicht abgerufene Pakete nach einer bestimmten Zeit löscht oder dein Puffer ist noch viel kleiner voreingestellt (<1024byte) als meiner.
BlackJack

Montag 9. Juni 2008, 16:00

Die Reihenfolge habe ich eingehalten.
Antworten