Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Dave

Alter Hase

  • »Dave« ist der Autor dieses Themas

Beiträge: 757

Wohnort: Berlin

  • Private Nachricht senden

1

14.09.2004, 20:51

Netzwerkprogrammierung - verschiedene Strukturen empfangen

Hi,

stehe vor folgendem Problem:
habe eine dll geschrieben, welche mir das verwenden von sockets erleichtern soll. läuft alles mehr oder weniger automatisiert ab. ich schicke immer ne struktur als "datenpaket".
wenn ich eine feste struktur habe ist das alles auch kein problem. empfangen usw. geht wunderbar.
aber wie macht man es, wenn man ein "datenpaket" erhält und nicht weiß, wie man es interpretieren soll. sprich man hat mehrer strukturen, die man verschicken möchte.
macht man es dann so, dass man an den anfang eine art steuerelement setzt, welches man dann beim empfangen manuell ausliest und jenachdem was drin steht dann die daten interpretiert?? finde ich jetzt etwas umständlich, aber mir fällt nichts besseres ein *g*
danke. dave.

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

2

14.09.2004, 22:14

Du musst bei sowas 1. die größe vorab senden und wie du schon festgestellt hast, für jeden Datentyp ein eigenes Steuerzeichen(sprich ein eigenes "Protokoll") definieren, sonst bekommt man es ja nie auseinander.

3

14.09.2004, 23:47

Eben....ich mein der gegenüber kann ja nicht wissen was denn da nun angekommen ist. Also muss eine Identifikation her. Diese als einfaches 32Bit Datenwort zu Definieren ist dabei die einfachste Wahl. Viele Nachrichten benötigen ja auch gar keine Daten.

Denn mit einer Sache musst du rechnen. Die Daten die du abschickst müssen nicht auch in der selben Reihenfolge beim Empfänger ankommen. Das ist besonders wichtig wenn du UDP benutzt.
Wichtig! Ich übernehme keinerlei Verantwortung für eventl. Datenverlust oder Schäden am Rechner ;D

Dave

Alter Hase

  • »Dave« ist der Autor dieses Themas

Beiträge: 757

Wohnort: Berlin

  • Private Nachricht senden

4

15.09.2004, 18:53

danke.

wie löst man sowas praktisch? also wie verschick ich meine struktur mit steuerzeichen vorne dran und lese sie dann auch wieder aus?? (benutze die mfc)

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

5

15.09.2004, 20:25

Beispiel:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct NachrichtentypA
{
    float xyz[3];
    int einmalPommesBitte;
    int danke;

    const int code;
};

struct NachrichtentypB
{
    char einKiloDatenBitte[1024];

    const int code;
};

// Jeder Nachrichtentyp bekommt einen Code.

const int NachrichtentypA::code = 1;
const int NachrichtentypB::code = 2;


Beim Senden einer Nachricht:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void sendeNachrichtentypA(const NachrichtentypA& n)
{
    // Puffer für zu sendende Nachricht (Code + Daten)

    char puffer[sizeof(int) + sizeof(n)];

    // Erst kommt der Nachrichtencode, ...

    *(static_cast<int*>(puffer)) = n.code;

    // ... und jetzt kommt die eigentliche Nachricht.

    memcpy(puffer + sizeof(int), &n, sizeof(n));

    // Nachricht senden

    sendeDaten(puffer, sizeof(puffer));
}


Beim Empfangen gehst Du umgekehrt vor: Erst liest Du den int-Wert, der ganz am Anfang der Nachricht steht. Dann weißt Du, wie Du die restlichen Daten zu interpretieren hast.
Hier könnte man auch schön Vererbung einsetzen: NachrichtentypA und NachrichtentypB könnten von einer Klasse Nachricht abgeleitet sein. Dann braucht man keine separate Sendefunktion für jeden Typ mehr.
Alternativ könnte man die Funktion "sendeNachrichtentypA" auch durch eine Template-Funktion ersetzen...

Dave

Alter Hase

  • »Dave« ist der Autor dieses Themas

Beiträge: 757

Wohnort: Berlin

  • Private Nachricht senden

6

15.09.2004, 20:28

vielen dank für die schnellen antworten.

Dave

Alter Hase

  • »Dave« ist der Autor dieses Themas

Beiträge: 757

Wohnort: Berlin

  • Private Nachricht senden

7

16.09.2004, 16:45

Hallo,

ich wollte mir gerade eine Methode schreiben, welche meine Daten sendet, unabhängig von der Struktur.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
void CMyServer::Send(int nType, void* pData, int nSize)
{
    char puffer[(sizeof(int) + nSize)];

    //// Erst kommt der Nachrichtencode, ... 

    memcpy(puffer, &nType, sizeof(nType));

    //// ... und jetzt kommt die eigentliche Nachricht. 

    memcpy(puffer + sizeof(int), pData, nSize); 

    //// Nachricht senden 

    sendeDaten(puffer, sizeof(puffer)); 
}


jedoch mekert er, dass er bei der Reservierung des Array einen Konstanten ausdruck erwartet. ich könnte anstatt mir die Größe als Parameter übergeben zu lassen sie mir ja auch selber mit

C-/C++-Quelltext

1
sizeof(&pData);


beschaffen, bin mir aber unsicher, ob das so geht und günstig ist. bei vielen windows funktionen muss man ja auch immer die größe mit übergeben, wird seinen grund haben...

außerdem mekert er, wenn ich den nachrichtencode so in den pufferschreiben will, wie david es vorgeschlagen hat:

C-/C++-Quelltext

1
2
// Erst kommt der Nachrichtencode, ... 

    *(static_cast<int*>(puffer)) = n.code;


Fehler: 'static_cast' : 'char []' kann nicht in 'int *' konvertiert werden.

8

16.09.2004, 16:59

Ich glaube eine Template-Methode wäre hier am besten geeignet. Das er meckert ist klar. Wenn man ein Statisches Array erstellen will, muss man eine Zahl angeben die nicht erst noch erechnet werden will.
Du must also an dieser Stelle (wenn du keine Template-Methode nutzt) das Array Dynamisch reservieren und am ende der Methode wieder freigeben.
Besser jedoch wäre wenn du dann einfach einen kleinen Pool anlegen würdest. Der zu Anfang immer 1Byte groß ist und sich dann bei bedarf immer vergrößert. Gelöscht wird der Pool erst dann wenn die Klasse entfernt wird.
So ersparst du dir dann immer die Allokation/Deallkoation von Speicher.

Das mit dem static_cast ist so eine Sache. Bin selbst auch noch nicht so 100% dahinter gestiegen. Aber probier mal den reinterpret_cast. Der soll, laut Stroustrup Buch, das Equivalent zum C-Cast sein. Naja klappt nicht immer :D

Wenn alles nichts Hilft, mach einfach ein C-Cast ;)
Wichtig! Ich übernehme keinerlei Verantwortung für eventl. Datenverlust oder Schäden am Rechner ;D

Dave

Alter Hase

  • »Dave« ist der Autor dieses Themas

Beiträge: 757

Wohnort: Berlin

  • Private Nachricht senden

9

16.09.2004, 17:38

vielen dank. ich glaube ich werde entweder ein dynamisches array verwenden (hätt ich eigentlich auch selbst drauf komment können) oder ein pool. hab irgendwie was gegen templates, ka warum...
kommt jedoch ganz drauf an was ein pool ist. hab ich glaub ich schonmal irgendwo gehört, aber nie verwendet... *g*

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

10

16.09.2004, 17:56

Zitat von »"Dave"«

ich könnte anstatt mir die Größe als Parameter übergeben zu lassen sie mir ja auch selber mit

C-/C++-Quelltext

1
sizeof(&pData);

Du meinst sicherlich *pData anstatt &pData, aber das geht nicht, denn man kann einen void*-Zeiger doch nicht dereferenzieren! &pData wäre vom Typ void** (Doppelzeiger).

Werbeanzeige