• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

[FRAGE] WebSockets Paketverlust

Bergmann89

New member
Hey Leute,

ich arbeite zur Zeit an einer Webseite die über WebSockets Daten mit dem Server austauscht. Das läuft so ab, das die Seite mehere Request (auf einmal) an den Server sendet und der diese dann alle nacheinander (nicht parallel) beantwortet. Nun habe ich das Problem, das ab und zu Pakete verloren gehen (zumindest bekomm ich für das Paket kein WebSocket.onmessage Event), was ja bei TCP eigentlich nicht der Fall sein kann. Zum Test habe ich mir eine kleine Test-Seite gebaut, die den Fehlerfall nachstellt:
Code:
this.packageSize            = 4096;
this.timerHandle            = 0;
this.receivedPackageSize    = 0; 
this.inbound                = [];
this.sendDataCnt            = 0;
this.parallelRequests       = 2;

/* Request:  uint32 (number of requested bytes ); */
/* Response: uint32 (number of send bytes); uint8[] data; */

var webSocket = new WebSocket('ws://10.1.0.92:6325', ['istest']);
webSocket.binaryType = 'arraybuffer';

function sendDataRequest()
{
    var buf  = new ArrayBuffer(4);
    var view = new DataView(buf, 0);
    view.setUint32(0, this.packageSize, true);
    for (var i = 0; i < this.parallelRequests; i++)
        webSocket.send(buf);
    $('#sendDataCnt')[0].innerHTML = this.sendDataCnt++;
}

webSocket.onopen = function()
{
    $('#log')[0].innerHTML += 'connected<br/>';
    this.timerHandle = setInterval(sendDataRequest, 100);
}.bind(this);

webSocket.onmessage = function(event)
{
    this.inbound.push.apply(this.inbound, new Uint8Array(event.data));
    if (this.receivedPackageSize == 0 && this.inbound.length >= 4)
    {
        var u8Arr = new Uint8Array(new ArrayBuffer(4));
        u8Arr.set(this.inbound.slice(0, 4));
        this.receivedPackageSize = new DataView(u8Arr.buffer).getUint32(0, true);
        this.inbound = this.inbound.slice(4);
        if (this.receivedPackageSize != this.packageSize)
        {
            clearInterval(this.timerHandle);
            $('#header')[0].innerHTML = 'ERROR: receivedPackageSize = ' + this.receivedPackageSize;
        }
        else
            $('#header')[0].innerHTML = 'receivedPackageSize = ' + this.receivedPackageSize;
        $('#data')[0].innerHTML = 'waiting for data...';
    }
    else if (this.inbound.length >= this.receivedPackageSize)
    {
        var u8Arr = new Uint8Array(new ArrayBuffer(this.receivedPackageSize));
        u8Arr.set(this.inbound.slice(0, this.receivedPackageSize));
        this.inbound = this.inbound.slice(this.receivedPackageSize);
        for (var i = 0; i < this.receivedPackageSize; i++)
        {
            if (u8Arr[i] != (i & 0xFF))
            {
                clearInterval(timerHandle);
                $('#data')[0].innerHTML = 'ERROR: invalid package data';
                break;
            }
        }
        $('#data')[0].innerHTML = 'data OK';
        this.receivedPackageSize = 0;
    }
}.bind(this);

webSocket.onerror = function(e)
{
    clearInterval(timerHandle);
    $('#log')[0].innerHTML += 'error<br/>';
    console.log(e);
}.bind(this);

webSocket.onclose = function()
{
    clearInterval(timerHandle);
    $('#log')[0].innerHTML += 'disconnected<br/>';
}.bind(this);
Ich denke das es daran liegt, das ich mehrere Request gleichezeitig absende und dann auf die Antworten warte. Umso mehr Requests ich auf eimal absende (siehe Zeile 19 und 20), umso schneller habe ich inkonsistente Daten. Hat das Problem schonmal jmd gehabt, oder weiß jmd wie ich das lösen kann? Eine Lösungsmöglichkeit wäre immer nur ein Request zu schicken und dann auf die Anwort zu warten. Da bei TCP-Verbindungen aber parallele Request möglich sein sollten würde ich die Lösung nur ungern (sozusagen als Notlösung) nutzen.
Der Server wurde in C++ implementiert und nutzt die libwebsockets Bibliothek.

MfG & Thx Bergmann.
 
Zuletzt bearbeitet von einem Moderator:
Ich würde immer nur einen Request zur gleichen Zeit abschicken, nie mehrere gleichzeitig. Das hat zur Folge (wie du richtig gesagt hast), dass du falsche Daten bekommst.
 
Hey,

wie oben geschrieben würde ich das nur ungern so machen, denn das löst nicht mein Problem sondern umgeht es nur. Ich will das Problem bei der Wurzel packen. Wenn die Daten nicht voneinander abhängig sind, dann sollten mehere Requests gleichzeitig ohne Probleme möglich sein. Der Server muss natürlich darauf achten, das er nicht 2 Daten-Pakete gleichzeitig sendet, da diese in mehere Ethernet-Frames zerteilt werden könnten und die Reihenfolge dann beim Client nicht mehr stimmt. Das ist bei mir aber nicht der Fall, der Server läuft in der Testumgebung nur mit einem Thread. Solange die Ethernet-Frames den Server in der richtigen Reihenfolge verlassen, dann sollten sie auch beim Client richtig ankommen (TCP halt).

MfG Bergmann
 
Zuletzt bearbeitet:
Äh... bei einem WebSocket hast du keine Requests, sondern ein Socket (wie schon der Name sagt). Du hast also, vereinfacht gesagt, zwei Leitungen, über die du Nachrichten zum Server schicken und vom Server empfangen kannst. Da die Daten nur sequenziell da hindurch können, sind deine "Requests" schon abhängig voneinander.

Durch den Nagle-Algorithmus kann es dann schon leicht passieren, dass die Antworten zusammengefasst werden und du nur ein Antwort-onmessage-Events bekommst. Hast du dir denn den rohen Netzwerkverkehr mal angesehen?
 
Solange die Ethernet-Frames den Server in der richtigen Reihenfolge verlassen, dann sollten sie auch beim Client richtig ankommen (TCP halt).
das eine packet kann theoretisch über russland und das andere über uruguay geroutet werden. (TCP halt)
welches kommt zuerst an?
und was ist denn serverseitig? kommen alle an? werden alle beantwortet?
 
Zurück
Oben