Du bist nicht angemeldet.

Werbeanzeige

Schwarzefee

Treue Seele

  • »Schwarzefee« ist der Autor dieses Themas

Beiträge: 140

Wohnort: Ost-Sachsen

Beruf: Programmierer

  • Private Nachricht senden

1

18.05.2019, 11:11

TCP-Verbindung - mehrere Packets auf einmal empfangen

Hi,

ich hab ein Client-Server Struktur einwickelt.
Der Server sendet dabei Pakete (im Prinzip byte-Arrays) an den Client:

C#-Quelltext

1
2
3
4
5
6
public static void SendPacketTo(NetworkStream stream, PacketBase packet)
{
     packet.SerializeToBuffer();
     stream.BeginWrite(packet.PacketBuffer.ToArray(), 0, packet.PacketBuffer.ToArray().Length, null, null);
     stream.Flush();
}


Der Client empfängt dann:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
void OnReceive(IAsyncResult result)
{
     if (this.PlayerSocket != null)
     {
         int byteArray = this.myStream.EndRead(result);
         byte[] myBytes = null;
         Array.Resize(ref myBytes, byteArray);
         Buffer.BlockCopy(this.asyncBuff, 0, myBytes, 0, byteArray);

         [...]
     }
}



Das funktioniert im Prinzip.

Wenn ich jetzt allerdings mehrere Pakete hintereinander verschicke, kommen sie als ein großer Bytestream beim Client an.
Wie geht man am Besten vor, um beim Client die einzelnen Pakete wieder zu bekommen?



Gruß

Nox

Supermoderator

Beiträge: 5 282

Beruf: Student

  • Private Nachricht senden

2

18.05.2019, 12:22

Da TCP garantiert, dass alles ankommt kannst du eine einfache Paketstruktur einführen, welche z.b. nur aus der Paketgröße besteht. Man schickt dann immer die Paketgröße zu erst und danach die Daten. Sobald ein Paket komplett gelesen wurde, wartet man auf eine neue Paketgröße. Vgl hier:

Quellcode

1
2
3
while(socket_open)
   if(bytes_to_read) recv(up_to_limit_equal_bytes_to_read)
   else bytes_to_read = recv(1)

Natürlich kann man ein Paket auch beliebig kompliziert aufbauen. Oft wird z.b. eine PaketID mitgeschickt, welche klarstellt, welche funktion das Paket hat (z.B. PACKET_ID_CHAT_MSG, PACKET_ID_UPDATE_OBJECTS, PACKET_ID_TRIGGER_EVENT).

Du solltest dabei beachten, dass je nach Implementierung ein recv auch nur "Teilstücke" eines Paket zurückliefern kann, wenn z.B. die Übertragung noch nicht abgeschlossen wurde. Man muss dann zu einem späteren Zeitpunkt nochmal nach dem Rest "fragen".
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

Schwarzefee

Treue Seele

  • »Schwarzefee« ist der Autor dieses Themas

Beiträge: 140

Wohnort: Ost-Sachsen

Beruf: Programmierer

  • Private Nachricht senden

3

18.05.2019, 13:52

Hi,

danke für die Antwort.
Das mit der Paket-ID hab ich schon so gemacht. In jedem Paket ist das erste Int der Paket-Typ.
Muss ich dann zu jedem Paket am Anfang noch die Paket Größe mitgeben?

Auf Client-Seite (ein Unity-Spiel) lese ich alle empfangenen Bytes in ein Asynchrones Byte-Array ein. Bei jedem Update hole ich mir dann aus dem Byte-Array die Pakete und leere dann das Async-Byte Array.
Bisher dachte ich, dass immer ein Paket aufs mal übertragen wird, allerdings wenn ich im Server mehrere Pakete hintereinander schicke, steht alles in einem großen Byte-Stream.

Meine Idee ist jetzt, dass ich nicht bei jedem Update das Async Byte-Array lösche (sobald ein Paket fertig eingelesen ist), sondern die ersten x-Bytes(je nach Paket-Größe) aus dem Async-Byte Array entferne, sobald ein Paket vollständig ist. Wenn neue Bytes empfangen werden, hänge ich sie dann immer hinten dran.


Würde das ion der Theorie so funktionieren? ;)


Gruß

Nox

Supermoderator

Beiträge: 5 282

Beruf: Student

  • Private Nachricht senden

4

19.05.2019, 21:33

es funktioniert auch in der Praxis so.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

Werbeanzeige