Hallo Leute!
ich bin schon seit Jahren aus der Praxis draussen und möchte mich mal wieder an ein Projekt ranwagen. Ich habe eine Dokumentation wie ein Paket aufgebaut sein muss, aber leider noch keine Idee wie man anhand dieser Anleitung das Paket in Quelltext fasst. Ich hoffe, das ihr mir weiterhelfen könnt. Die Anleitung sieht wie folgt aus:
32-bit unsigned integer
1 byte bits 7..0 of value
1 byte bits 15..8 of value
1 byte bits 23..16 of value
1 byte bits 31..24 of value
Word
int32 Size Number of bytes in word, excluding trailing null byte.
char[] Content Word contents -- must not contain any null bytes.
char Terminator Trailing null byte.
Packet
int32 Sequence Bit 31: 0 = The command in this
command/response pair originated on the
server 1 = The command in this
command/response pair originated on the client.
Bit 30: 0 = Request, 1 = Response
Bits 29..0: Sequence number
(this is used to match requests/responses
in a full duplex transmission).
int32 Size Total size of packet, in bytes.
int32 NumWords Number of words following the packet header.
Word[N] Words N words
32-bit unsigned integer
1 byte bits 7..0 of value
1 byte bits 15..8 of value
1 byte bits 23..16 of value
1 byte bits 31..24 of value
Word
int32 Size Number of bytes in word, excluding trailing null byte.
char[] Content Word contents -- must not contain any null bytes.
char Terminator Trailing null byte.
Packet
int32 Sequence Bit 31: 0 = The command in this
command/response pair originated on the
server 1 = The command in this
command/response pair originated on the client.
Bit 30: 0 = Request, 1 = Response
Bits 29..0: Sequence number
(this is used to match requests/responses
in a full duplex transmission).
int32 Size Total size of packet, in bytes.
int32 NumWords Number of words following the packet header.
Word[N] Words N words
32-bit unsigned integer
1 byte bits 7..0 of value
1 byte bits 15..8 of value
1 byte bits 23..16 of value
1 byte bits 31..24 of value
Word
int32 Size Number of bytes in word, excluding trailing null byte.
char[] Content Word contents -- must not contain any null bytes.
char Terminator Trailing null byte.
Packet
int32 Sequence Bit 31: 0 = The command in this
command/response pair originated on the
server 1 = The command in this
command/response pair originated on the client.
Bit 30: 0 = Request, 1 = Response
Bits 29..0: Sequence number
(this is used to match requests/responses
in a full duplex transmission).
int32 Size Total size of packet, in bytes.
int32 NumWords Number of words following the packet header.
Word[N] Words N words
A packet cannot be more than 16384 bytes in size.
Kann mir bitte jemand helfen das ganze in Quelltext zu fassen damit ich mal den Buzug zueinander verstehe. Ich weiß momentan gar nicht wie ich anfangen soll
Ich hab mir jetzt das PDF _nicht_ angeschaut, jedoch vermute ich, daß die Daten per Ethernet verschickt werden sollen.
Hierbei ist darauf zu achten, daß die Struktur gepackt wird.
D.h. das die Daten alle hintereinander im Speicher liegen und dann auch so verschickt werden.
Deine struct Word wird vermutlich als 3x32 Bit Wert im Speicher abgelegt sein, was durch das Packen verhindert wird.
Im Builder geht das Packen so:
C/C++ Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#pragma pack(push,1) //packen beginnen struct Word
{
unsigned int Size;
char Content[128];
char Terminator;
};
struct Paket
{
unsigned int Sequence;
unsigned int Size;
unsigned int NumWords;
Word words[];
};
#pragma pack(pop) //packen beenden
C/C++ Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#pragma pack(push,1) //packen beginnen struct Word
{
unsigned int Size;
char Content[128];
char Terminator;
};
struct Paket
{
unsigned int Sequence;
unsigned int Size;
unsigned int NumWords;
Word words[];
};
#pragma pack(pop) //packen beenden
C/C++ Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#pragma pack(push,1) //packen beginnen struct Word
{
unsigned int Size;
char Content[128];
char Terminator;
};
struct Paket
{
unsigned int Sequence;
unsigned int Size;
unsigned int NumWords;
Word words[];
};
#pragma pack(pop) //packen beenden
Ein weiterer Tipp, was bezüglich Ethernet, meiner Meinung nach, sehr wichtig ist, schau dir das Programm Wireshark an. Dies ist ein Ethernet Sniffer, womit Du sehen kannst, was deine Anwendung wirklich verschickt.
Das kann so auch nicht funktionieren, weil deine char Arrays immer eine fixe Länge von 128 haben. Im Protokoll ist definiert, dass jedes Word ein Attribut Content hat, das von genau einem abschließenden Nullbyte terminiert wird. Eigentlich brauchst du keine eigene Datenstrukturen für dein Paket, denn im Grunde sind die Daten nur Zeichenketten, die in einem bestimmten Format abgesendet werden. Um ein Paket zusammenzubauen kannst du Klassen der STL benutzen:
Kann es sein das die Standard TCP Client Komponente von der BCB
Auswahl nicht mit gängigen Standards zurecht kommt und nur der BCB TCP Client mit dem BCB TCP Server kommunizieren kann?
Zuletzt bearbeitet von Zero01 am 13:38:23 23.01.2012, insgesamt 3-mal bearbeitet
Die Logindaten entsprechen nicht der Realität in diesem Beispiel. So wie es aussieht kommt das Paket richtig beim Server an, da ich nun direkt ein disconnect bekomme wenn ich dieses erneut sende. Aber wie bewege ich das ClientSocket dazu Daten entgegenzunehmen?
Nein, habe ich nicht.
Du kannst strcpy hier nicht verwenden, da es sich bei dem Puffer nicht um Klartext sondern um Binärdaten handelt. Dabei ist es sehr wahrscheinlich, dass der Puffer mehrere Nullbytes enthält und strcpy ab dem ersten nicht mehr weiterkopiert. Ersetz´ den zitierten Code mal durch
Super!!! ich weiß gar nicht wie ich dir danken soll. Der Server kommuniziert nun endlich mit meinem Client. Jetzt muss ich nur noch deine Funktion wie das Paket formatiert wird richtig verstehen um das Paket vom Server wiederum zu entschlüsseln
void read_packet(unsigned char *readbuff, unsigned int length)
{
unsigned int headersize = 4;
// Sequence ID lesen und in Form1->Memo1 ausgeben
// Gesamtgröße lesen
// Anzahl der Wörter lesen
// Wörter lesen und in Form1->Memo1 ausgeben
(so wie ich das sehe ab dem 12. byte das Pakets)
}
Wenn ich das Datenfelde direkt ab dem 12. Byte aus dem Paket auslese und im Memo ausgebe bekomme ich nur Zahlensalat. Normalerweise sollte doch ab dem 12. Byte die Wörter kommen Die for Schleife habe ich wieder gelöscht weil dies ein vollkommen falscher Lösungsansatz war. Bin ich auf der richtigen Spur oder ist der Ansatz falsch?
Das gesendete Paket und das zu empfangende Paket sind absolut identisch vom Aufbau her
Zuletzt bearbeitet von Zero01 am 19:14:41 23.01.2012, insgesamt 3-mal bearbeitet
So funktioniert TCP/IP nicht. Du kannst nicht davon ausgehen, dass dein komplettes Telegramm mit einem ReceiveBuf Aufruf empfangen werden kann. Außerdem hast du noch einen anderen dicken Bock in deinem Code:
C/C++ Code:
Socket->ReceiveBuf(buffer,sizeof(buffer));
C/C++ Code:
Socket->ReceiveBuf(buffer,sizeof(buffer));
C/C++ Code:
Socket->ReceiveBuf(buffer,sizeof(buffer));
sizeof(buffer) liefert 4, da buffer ein Zeiger ist und Zeiger nun mal nur 4 Byte im Speicher belegen (zumindest bei Windows 32bit). Du liest also nur 4 Byte, kein Wunder, dass ab Position 12 nix Vernünftiges steht. Auch das Verwenden von malloc/free ist in C++ völlig überflüssig (zumal ich deinem Code nirgendwo ein free sehe). Deine receive Funktion könnte z.B. so aussehen:
Als nächstes musst du die eingehenden Daten an einen Empfangspuffer anhängen. Jedes Mal, wenn du Daten empfängst musst du Folgende Schritte machen:
1) empfangene Daten an Empfangspuffer anhängen
2) prüfen, ob mind. 8 Byte im Empfangspuffer stehen (da ab Byte 4 die Gesamttelegrammlänge steht)
3) wenn weniger als 8 Byte empfangen worden sind => 9)
4) Gesamttelegrammlänge bestimmen
5) prüfen, ob entsprechend viele Daten im Empfangspuffer stehen. Wenn nein => 9)
6) Telegrammdaten bestimmen und behandeln
7) behandelte Telegrammdaten vom Anfang des Empfangspuffers löschen
8) => 2)
9) auf weitere Daten warten
Dir fehlen offensichtlich noch Grundlagen, insbesondere bei der Verwendung der STL. Fast sämtliche dynamische Speicheranforderungen lassen sich durch Klassen der STL effizienter und robuster realisieren als mit malloc/free. Vielleicht solltest du dir ein modernes C++ Buch besorgen und erst ein Mal etwas lesen.
_________________ 1. Dies ist die erste Regel des Tautologieclubs.
Stimmt,jetzt fällt es mir wieder ein. Wenn ich malloc benutze macht es nur Sinn wenn die Funktion jediglich den Pointer auf den allokierten Speicher zurück gibt, abgearbeitet wird und dann anschliessend mit free() freigegeben wird. free() innerhalb der Funktion geht nicht, da nach dem return kein weiterer code abgehandelt wird und davor eine Speicherzugriffsverletzung entstehen würde, weil ein Pointer auf eine Speicheradresse aufgerufen wird die nicht mehr existiert.
Mit Vektoren in diesem Umfang bin ich jetzt zum ersten mal durch dich in Kontakt gekommen und werde mich da fix einlesen. Durch deine Erläuterungen leuchtet mir ein, dass dies ein wirklich gutes Werkzeug zur dynamischen Speicherbelegung ist. Entschuldigt bitte die ein oder andere sehr naive Frage. Hab jetzt seit 6 Jahren zum ersten mal wieder den CBuilder 6 vor Augen und in dieser Zeit scheint sehr vieles auf der Strecke geblieben zu sein. Ich bemühe mich wieder reinzukommen. Vielen Dank für die super Erklärungen und die Starthilfe!!!!
Noch eine Frage
C/C++ Code:
&ReceiveBuffer[0]
C/C++ Code:
&ReceiveBuffer[0]
C/C++ Code:
&ReceiveBuffer[0]
0 ist der Index ab dem gelesen werden soll und Receive.Length gibt an bis wohin gelesen werden soll in dem Funktionsaufruf Socket->ReceiveBuf()?
TCP arbeitet ja mit Fehlerkorrektur und deshalb kann es vorkommen das ein nicht richtig übertragenes Paket erneut gesendet wird. Wenn ein Datensatz das TCP Frame in seiner Größe überschreitet, kapselt TCP die Daten in mehrere Pakete. Daher kann ich nicht von ausgehen das alles in einem Paket übertragen wird.
Richtig so?
Zuletzt bearbeitet von Zero01 am 19:06:58 24.01.2012, insgesamt 3-mal bearbeitet
Nochmal: Dir fehlen Grundlagen. Der Code, den du hier vorgestellt hast, zeigt deutlich, dass du die Problematik nicht vollständig erfasst hast und auch nicht in der Lage bist, eine Lösung umzusetzen. Sich Codeschnipsel aus dem Internet zusammenzusuchen und sich irgendwas zusammenzuschrauben führt in der Regel nicht zum gewünschten Ergebnis. Aber mach dir nix draus, wir haben alle mal angefangen, so ganz auf dem Holzweg bist du nicht
Vielleicht solltest du den Computer einfach mal für ´ne Stunde ausmachen und dir in Ruhe überlegen, was du erreichen willst und wie du das erreichen kannst. Geh im Kopf (und einem Blatt Papier) mal durch, welche Fälle auftreten können und wie man das in den Griff bekommt.
Was passiert denn, wenn bei deinem letzten Code jedes Byte einzeln ankommt?
_________________ 1. Dies ist die erste Regel des Tautologieclubs.
//Frames sammeln und anhängen bis Paket vollständig übertragen ist.
Framesammler.insert(Framesammler.end(), ReceiveBuffer.begin(), ReceiveBuffer.end());
//Hilfsvariable um Übertragungsende zu bestimmen.
//Paketgröße aus dem Paketheader holen. if(Framesammler.size() >= 4)
isPaketsizereached = Framesammler[4];
if(Framesammler.size() > 12 && isPaketsizereached == Framesammler.size())
{
String daten = "";
for(unsigned int i = 12; i <= Framesammler.size(); i++)
{
daten += Framesammler[i] ;
}
Memo1->Lines->Add(daten) ;
//Da vollständig übertragen Sammelpuffer und Paketgröße zurücksetzen für nächste Pakete
Framesammler.clear();
isPaketsizereached = 0;
//Frames sammeln und anhängen bis Paket vollständig übertragen ist.
Framesammler.insert(Framesammler.end(), ReceiveBuffer.begin(), ReceiveBuffer.end());
//Hilfsvariable um Übertragungsende zu bestimmen.
//Paketgröße aus dem Paketheader holen. if(Framesammler.size() >= 4)
isPaketsizereached = Framesammler[4];
if(Framesammler.size() > 12 && isPaketsizereached == Framesammler.size())
{
String daten = "";
for(unsigned int i = 12; i <= Framesammler.size(); i++)
{
daten += Framesammler[i] ;
}
Memo1->Lines->Add(daten) ;
//Da vollständig übertragen Sammelpuffer und Paketgröße zurücksetzen für nächste Pakete
Framesammler.clear();
isPaketsizereached = 0;
//Frames sammeln und anhängen bis Paket vollständig übertragen ist.
Framesammler.insert(Framesammler.end(), ReceiveBuffer.begin(), ReceiveBuffer.end());
//Hilfsvariable um Übertragungsende zu bestimmen.
//Paketgröße aus dem Paketheader holen. if(Framesammler.size() >= 4)
isPaketsizereached = Framesammler[4];
if(Framesammler.size() > 12 && isPaketsizereached == Framesammler.size())
{
String daten = "";
for(unsigned int i = 12; i <= Framesammler.size(); i++)
{
daten += Framesammler[i] ;
}
Memo1->Lines->Add(daten) ;
//Da vollständig übertragen Sammelpuffer und Paketgröße zurücksetzen für nächste Pakete
Framesammler.clear();
isPaketsizereached = 0;
}
ReceiveBuffer.clear();
Meun DocShoe!
Mein Ziel ist nicht das abkupfern des Phytonquelltextes sondern das Wiso Weshalb Warum. Das mit dem Computerausschalten, sich mal Hinsetzen und deine Hinweiße zu befolgen hat hoffentlich anhand des hier gezeigten Ergebnisses verdeutlicht, dass es bei mir noch nicht Hoffnungslos ist Der Befehl "serverinfo" sendet mehrere Pakete hintereinander und diese hängen jetzt schön aneinander im Hilfspuffer den ich dann Auslese ohne den ganzen Headerkram drin stehen zu haben.
Gestern kurz vorm einschlafen kam mir noch ein Gedanke die eigentlichen Paketdaten in 4Byte Schnipsel rauszukopieren und ein '0x' davor zu setzen um den Lösungsweg mal nach Hexadezimal zu versuchen um endlich aus dem Zahlenwirrwar Buchstaben zu erhalten. Da ich aber noch keinen genauen Anhaltspunkt habe überlege ich ob das zum Ziel führt. Was meinst du?
Zuletzt bearbeitet von Zero01 am 17:16:38 25.01.2012, insgesamt 3-mal bearbeitet
Wow! Das ist ja fast gut Ich würde die Hilfsvariable isPaketsizereached anders nennen, ein guter Name wäre z.B. TelegramLength.
Du hast immer noch mehrere Fehler drin:
- wenn z.B. 1.5 Telegramme in deinem Puffer stehen
darfst du nur soviele Daten entnehmen, wie das Telegramm lang ist
musst du soviele Daten aus dem Puffer entfernen, wie das Telegramm lang ist
- du greifst auf den festen Index 4 des Buffers zu, da steht allerdings nur das niederwertigste Byte der Telegrammlänge drin. Richtigerweise müsstest du die Bytes der Indizes 5-7 noch berücksichtigen (und entsprechend bitshiften).
Die erste Überprüfung gegen 4 ist falsch, denn in den ersten 4 Bytes steht nur die Sequence ID und nicht die Telegrammlänge. Danach musst du gegen TelegramLength und nicht gegen 12 prüfen. Ausserdem musst du noch den Fall betrachten, dass mehrere Telegramme im Puffer stehen können.
// entferne behandelte Daten vom Anfang des Puffers
// ggf. stehen weitere Telegramme im Puffer, weiterer Durchlauf notwendig
Done = false;
}
}
}
while( !Done );
Edit:
Was das die Ausgabe in´s Memo angeht: Hexadezimale Ausgabe halte ich nicht für sooo schlau, daraus erkennt man nicht viel. Klartext ist da wesentlich besser. Und wie der Zufall so will gibt´s für std::string nen schönen Konstruktor, der dir Abschnitte aus einem Vektor herausfilettiert:
//Frames sammeln und anhängen bis Paket vollständig übertragen ist.
Framesammler.insert(Framesammler.end(), ReceiveBuffer.begin(), ReceiveBuffer.end());
//Hilfsvariable um Übertragungsende zu bestimmen.
//Paketgröße aus dem Paketheader holen. if(Framesammler.size() >= 4)
{
//Bitshift der einzelnen bytes zur Ermittlung der Paketgröße
TelegramLength = Framesammler[4] >> Framesammler[5] >> Framesammler[6] >> Framesammler[7] ;
}
if(Framesammler.size() >= TelegramLength)
{
/*
//Reine Telegrammlänge abarbeiten
for(int x = 12; x < TelegramLength; x++)
{
std::string Line(Framesammler.begin() + x, Framesammler.end());
Memo1->Lines->Add(Line.c_str());
}
Noch Fehlerhaft!
*/
bool done = false;
bool deletebuffer = false;
do
{
//Wenn im Puffer mehr als das abgearbeitete Telegram steht if(Framesammler.size() > TelegramLength)
{
//Frames sammeln und anhängen bis Paket vollständig übertragen ist.
Framesammler.insert(Framesammler.end(), ReceiveBuffer.begin(), ReceiveBuffer.end());
//Hilfsvariable um Übertragungsende zu bestimmen.
//Paketgröße aus dem Paketheader holen. if(Framesammler.size() >= 4)
{
//Bitshift der einzelnen bytes zur Ermittlung der Paketgröße
TelegramLength = Framesammler[4] >> Framesammler[5] >> Framesammler[6] >> Framesammler[7] ;
}
if(Framesammler.size() >= TelegramLength)
{
/*
//Reine Telegrammlänge abarbeiten
for(int x = 12; x < TelegramLength; x++)
{
std::string Line(Framesammler.begin() + x, Framesammler.end());
Memo1->Lines->Add(Line.c_str());
}
Noch Fehlerhaft!
*/
bool done = false;
bool deletebuffer = false;
do
{
//Wenn im Puffer mehr als das abgearbeitete Telegram steht if(Framesammler.size() > TelegramLength)
{
//Frames sammeln und anhängen bis Paket vollständig übertragen ist.
Framesammler.insert(Framesammler.end(), ReceiveBuffer.begin(), ReceiveBuffer.end());
//Hilfsvariable um Übertragungsende zu bestimmen.
//Paketgröße aus dem Paketheader holen. if(Framesammler.size() >= 4)
{
//Bitshift der einzelnen bytes zur Ermittlung der Paketgröße
TelegramLength = Framesammler[4] >> Framesammler[5] >> Framesammler[6] >> Framesammler[7] ;
}
if(Framesammler.size() >= TelegramLength)
{
/*
//Reine Telegrammlänge abarbeiten
for(int x = 12; x < TelegramLength; x++)
{
std::string Line(Framesammler.begin() + x, Framesammler.end());
Memo1->Lines->Add(Line.c_str());
}
Noch Fehlerhaft!
*/
bool done = false;
bool deletebuffer = false;
do
{
//Wenn im Puffer mehr als das abgearbeitete Telegram steht if(Framesammler.size() > TelegramLength)
{
//Wenn vollständig übertragen Sammelpuffer zurücksetzen für nächste Pakete,ansonsten neu formaierten Puffer beibehalten if (deletebuffer == true)
Framesammler.clear();
}
ReceiveBuffer.clear();
}
C/C++ Code:
//Reine Telegrammlänge abarbeiten for(int x = 12; x < TelegramLength; x++)
{
std::string Line(Framesammler.begin() + x, Framesammler.end());
Memo1->Lines->Add(Line.c_str());
}
C/C++ Code:
//Reine Telegrammlänge abarbeiten for(int x = 12; x < TelegramLength; x++)
{
std::string Line(Framesammler.begin() + x, Framesammler.end());
Memo1->Lines->Add(Line.c_str());
}
C/C++ Code:
//Reine Telegrammlänge abarbeiten for(int x = 12; x < TelegramLength; x++)
{
std::string Line(Framesammler.begin() + x, Framesammler.end());
Memo1->Lines->Add(Line.c_str());
}
Puhh, da versteh ich noch nicht so ganz wie ich an die ganzen Wörter ran komme. Wörter werden ausgegeben aber sehen noch wie folgt aus mit Leerspalten im Memo
und Sonderzeichen dazwischen:
MP_Subway
P_Subway
_Subway
Subway
ubway
bway
way
ay
y
0
1
2
489
89
9
489
89
9
0
true
rue
ue
e
true
rue
ue
e
false
alse
lse
se
e
26100
6100
100
00
0
20104
0104
104
04
4
EU
U
ams
ms
s
DE
E
Es ist mir klar das durch die for Schleife mit stetig ansteigendem X nur Salat rauskommt, aber ich möchte nur diese Funktion des std::string verstehen um es debugen zu können
//Frames sammeln und anhängen bis Paket vollständig übertragen ist.
Framesammler.insert(Framesammler.end(), ReceiveBuffer.begin(), ReceiveBuffer.end());
//Hilfsvariable um Übertragungsende zu bestimmen.
//Paketgröße aus dem Paketheader holen. if(Framesammler.size() >= 4)
{
//Bitshift der einzelnen bytes zur Ermittlung der Paketgröße
TelegramLength = Framesammler[4] >> Framesammler[5] >> Framesammler[6] >> Framesammler[7] ;
}
if(Framesammler.size() >= TelegramLength)
{
//Reine Telegrammlänge abarbeiten
String temp = "";
for(unsigned int x = 16; x < TelegramLength; x++)
{
std::string Line(Framesammler.begin() + x , Framesammler.begin() + x + 1);
temp = temp + Line.c_str();
}
Memo1->Lines->Add(temp);
bool done = false;
do
{
//Wenn im Puffer mehr als das abgearbeitete Telegram steht
//Wenn der Puffer das abgearbeitete Paket vollständig enthält if(Framesammler.size() >= TelegramLength)
{
//Vollständiges und zuvor abgearbeitetes Paket im Puffer ausschneiden und folgende Daten an den Anfang stellen
Tempbuffer.insert(Tempbuffer.end(),Framesammler.begin() + TelegramLength, Framesammler.end());
Framesammler.clear();
Framesammler.insert(Framesammler.end(),Tempbuffer.begin(),Tempbuffer.end());
//Frames sammeln und anhängen bis Paket vollständig übertragen ist.
Framesammler.insert(Framesammler.end(), ReceiveBuffer.begin(), ReceiveBuffer.end());
//Hilfsvariable um Übertragungsende zu bestimmen.
//Paketgröße aus dem Paketheader holen. if(Framesammler.size() >= 4)
{
//Bitshift der einzelnen bytes zur Ermittlung der Paketgröße
TelegramLength = Framesammler[4] >> Framesammler[5] >> Framesammler[6] >> Framesammler[7] ;
}
if(Framesammler.size() >= TelegramLength)
{
//Reine Telegrammlänge abarbeiten
String temp = "";
for(unsigned int x = 16; x < TelegramLength; x++)
{
std::string Line(Framesammler.begin() + x , Framesammler.begin() + x + 1);
temp = temp + Line.c_str();
}
Memo1->Lines->Add(temp);
bool done = false;
do
{
//Wenn im Puffer mehr als das abgearbeitete Telegram steht
//Wenn der Puffer das abgearbeitete Paket vollständig enthält if(Framesammler.size() >= TelegramLength)
{
//Vollständiges und zuvor abgearbeitetes Paket im Puffer ausschneiden und folgende Daten an den Anfang stellen
Tempbuffer.insert(Tempbuffer.end(),Framesammler.begin() + TelegramLength, Framesammler.end());
Framesammler.clear();
Framesammler.insert(Framesammler.end(),Tempbuffer.begin(),Tempbuffer.end());
//Frames sammeln und anhängen bis Paket vollständig übertragen ist.
Framesammler.insert(Framesammler.end(), ReceiveBuffer.begin(), ReceiveBuffer.end());
//Hilfsvariable um Übertragungsende zu bestimmen.
//Paketgröße aus dem Paketheader holen. if(Framesammler.size() >= 4)
{
//Bitshift der einzelnen bytes zur Ermittlung der Paketgröße
TelegramLength = Framesammler[4] >> Framesammler[5] >> Framesammler[6] >> Framesammler[7] ;
}
if(Framesammler.size() >= TelegramLength)
{
//Reine Telegrammlänge abarbeiten
String temp = "";
for(unsigned int x = 16; x < TelegramLength; x++)
{
std::string Line(Framesammler.begin() + x , Framesammler.begin() + x + 1);
temp = temp + Line.c_str();
}
Memo1->Lines->Add(temp);
bool done = false;
do
{
//Wenn im Puffer mehr als das abgearbeitete Telegram steht
//Wenn der Puffer das abgearbeitete Paket vollständig enthält if(Framesammler.size() >= TelegramLength)
{
//Vollständiges und zuvor abgearbeitetes Paket im Puffer ausschneiden und folgende Daten an den Anfang stellen
Tempbuffer.insert(Tempbuffer.end(),Framesammler.begin() + TelegramLength, Framesammler.end());
Framesammler.clear();
Framesammler.insert(Framesammler.end(),Tempbuffer.begin(),Tempbuffer.end());
Aber immernoch Headerdaten die sich im reinen Datenpuffer zwischenmogeln wenn mehrere Pakete gesendet werden. Eine Endlosschleife entsteht jetzt nicht mehr, aber die Daten werden noch genauso angezeigt wie in dem verlinkten Bild.
Zuletzt bearbeitet von Zero01 am 01:17:22 26.01.2012, insgesamt 1-mal bearbeitet
- Zeile 12-17
Du prüfst gegen Länge 4, greifst aber auf Elemente 5-8 zu. Die Bestimmung der Telegrammlänge ist zudem noch falsch. Lies dir noch ein Mal das Kapitel zum Thema bit shifts durch.
- Zeile 23-30
WTF? Du baust für jedes einzelne Zeichen einen String und hängst den wieder an den Ausgabestring an. Das geht besser, weil du doch schon weißt, wie lang der String ist (steht so im Telegramm).
- Zeile 43-49
Hier kommt man auch ohne temp. Puffer aus. Du sollst nur die Daten des Telegramms vom Anfang des Puffers löschen, das geht mit einem erase Aufruf.
- Zeile 52 und Zeile 58
Die korrekte Telegrammlänge ist mit Sicherheit nicht die Anzahl der verbleibenden Bytes im Empfangspuffer.
also eigentlich fast alles... also nochmal von vorne. Immerhin stimmt das Empfangen und Speichern der Telegrammdaten.
1) Stehen genügend Daten bereit für den Telegrammkopf (Sequence ID + Telegrammlänge. Wieviel Bytes haben 2 int32?)? Wenn nein, dann weiter bei 7)
2) Telegrammlänge aus Bytes 5-8 bestimmen
3) Stehen genügend Daten für das Telegramm bereit? Wenn nein, dann weiter bei 7)
4) Behandle die ersten N Bytes des Puffers
5) Entferne die ersten N Bytes des Puffers
6) Zurück zu 1)
7) Zu wenig Daten für Telegramm vorhanden
_________________ 1. Dies ist die erste Regel des Tautologieclubs.
Soweit habe ich jetzt all deine Korrekturen umgesetzt, allerdings Blick ich durchs Bitshifting noch nicht ganz durch. Ich veranlasse einen Linksshift, aber um wieviel Bit? 1 oder alle 8 pro byte?
Zudem habe ich die Funktion noch mal grundliegend umstrukturiert, ich denke so macht es jetzt eher Sinn:
//Frames sammeln und anhängen bis Paket vollständig übertragen ist.
Framesammler.insert(Framesammler.end(), ReceiveBuffer.begin(), ReceiveBuffer.end());
//Wenn der Puffer Paketdaten enthält dann prüfe und verarbeite if(Framesammler.size() > 0)
{
bool done = false;
do
{
//Paketgröße aus dem Paketheader holen.
//Sequence ID + Telegrammlänge. Wieviel Bytes haben 2 int32? = 8byte! if(Framesammler.size() >= 8)
{
//Bitshift der einzelnen bytes zur Ermittlung der Paketgröße
TelegramLength = 0;
TelegramLength += Framesammler[5] << 8;
TelegramLength += Framesammler[6] << 8;
TelegramLength += Framesammler[7] << 8;
TelegramLength += Framesammler[8] << 8;
//Vollständiges und zuvor abgearbeitetes Pakets im Puffer ausschneiden und folgende Daten an den Anfang stellen
Framesammler.erase(Framesammler.begin(),Framesammler.begin() + TelegramLength);
done = true;
//Prüfen ob sich noch ein weiteres vollständiges Telegram im Puffer befindet
//Wenn nicht, empfange weiter if (Framesammler.size() >= 8)
{
//Bitshift der einzelnen bytes zur Ermittlung der Paketgröße
//Noch nicht angepasst, siehe oben.....
TelegramLength = 0;
TelegramLength = Framesammler[5] << Framesammler[6] << Framesammler[7] << Framesammler[8];
if (Framesammler.size() >= TelegramLength)
continue;
//Frames sammeln und anhängen bis Paket vollständig übertragen ist.
Framesammler.insert(Framesammler.end(), ReceiveBuffer.begin(), ReceiveBuffer.end());
//Wenn der Puffer Paketdaten enthält dann prüfe und verarbeite if(Framesammler.size() > 0)
{
bool done = false;
do
{
//Paketgröße aus dem Paketheader holen.
//Sequence ID + Telegrammlänge. Wieviel Bytes haben 2 int32? = 8byte! if(Framesammler.size() >= 8)
{
//Bitshift der einzelnen bytes zur Ermittlung der Paketgröße
TelegramLength = 0;
TelegramLength += Framesammler[5] << 8;
TelegramLength += Framesammler[6] << 8;
TelegramLength += Framesammler[7] << 8;
TelegramLength += Framesammler[8] << 8;
//Vollständiges und zuvor abgearbeitetes Pakets im Puffer ausschneiden und folgende Daten an den Anfang stellen
Framesammler.erase(Framesammler.begin(),Framesammler.begin() + TelegramLength);
done = true;
//Prüfen ob sich noch ein weiteres vollständiges Telegram im Puffer befindet
//Wenn nicht, empfange weiter if (Framesammler.size() >= 8)
{
//Bitshift der einzelnen bytes zur Ermittlung der Paketgröße
//Noch nicht angepasst, siehe oben.....
TelegramLength = 0;
TelegramLength = Framesammler[5] << Framesammler[6] << Framesammler[7] << Framesammler[8];
if (Framesammler.size() >= TelegramLength)
continue;
//Frames sammeln und anhängen bis Paket vollständig übertragen ist.
Framesammler.insert(Framesammler.end(), ReceiveBuffer.begin(), ReceiveBuffer.end());
//Wenn der Puffer Paketdaten enthält dann prüfe und verarbeite if(Framesammler.size() > 0)
{
bool done = false;
do
{
//Paketgröße aus dem Paketheader holen.
//Sequence ID + Telegrammlänge. Wieviel Bytes haben 2 int32? = 8byte! if(Framesammler.size() >= 8)
{
//Bitshift der einzelnen bytes zur Ermittlung der Paketgröße
TelegramLength = 0;
TelegramLength += Framesammler[5] << 8;
TelegramLength += Framesammler[6] << 8;
TelegramLength += Framesammler[7] << 8;
TelegramLength += Framesammler[8] << 8;
//Vollständiges und zuvor abgearbeitetes Pakets im Puffer ausschneiden und folgende Daten an den Anfang stellen
Framesammler.erase(Framesammler.begin(),Framesammler.begin() + TelegramLength);
done = true;
//Prüfen ob sich noch ein weiteres vollständiges Telegram im Puffer befindet
//Wenn nicht, empfange weiter if (Framesammler.size() >= 8)
{
//Bitshift der einzelnen bytes zur Ermittlung der Paketgröße
//Noch nicht angepasst, siehe oben.....
TelegramLength = 0;
TelegramLength = Framesammler[5] << Framesammler[6] << Framesammler[7] << Framesammler[8];
if (Framesammler.size() >= TelegramLength)
continue;
Meun Doc!
Soweit habe ich jetzt all deine Korrekturen umgesetzt, allerdings Blick ich durchs Bitshifting noch nicht ganz durch.
Nein, hast du nicht.
Zero01 schrieb:
Ich veranlasse einen Linksshift, aber um wieviel Bit? 1 oder alle 8 pro byte?
Hängt vom Byte ab. Also ganz langsam: Ein int32 besteht aus 4 Byte. Jedes dieser Bytes hat eine bestimmte Wertigkeit (zum Vergleich: Dezimalsystem. Jede Stelle besteht aus einer Ziffer, aber abhängig von der Stelle hat diese Ziffer eine andere Wertigkeit. Ein Byte ist für die Bits 0-7, eins für 8-15, noch eins für 16-23 und schließlich eins für 24-31. In deiner Protokollbeschreibung ist beschrieben, welches Byte welche Wertigkeit hat.
Zero01 schrieb:
Zudem habe ich die Funktion noch mal grundliegend umstrukturiert, ich denke so macht es jetzt eher Sinn:
Ich glaube nicht . Du hast viel zu viele Überprüfungen für die Telegrammgröße drin, du kommst mit nur 2 aus (Tipp: Wenn 8 oder mehr Bytes im Puffer stehen, dann stehen auch mehr als 0 Bytes drin).
Die Bestimmung der Telegrammlänge stimmt immer noch nicht, aber das weißt du ja bereits.
Bei der Softwareentwicklung macht man sich übrigens vorher Gedanken zum Algorithmus und setzt diesen dann in Code um. Man probiert nicht solange, bis es irgendwann zufällig funktioniert. Du machst letzteres...
Langsam gehe ich auf dem Zahnfleisch... vielleicht erbarmt sich ja jemand anderes, das hier zu lösen, ich kann langsam nicht mehr
_________________ 1. Dies ist die erste Regel des Tautologieclubs.
Langsam gehe ich auf dem Zahnfleisch... vielleicht erbarmt sich ja jemand anderes, das hier zu lösen, ich kann langsam nicht mehr
Oh nicht wegen mir. Entschuldige bitte
Ich weiß das ich einiges noch nicht ganz durchblicke und evtl. auch dafür zu doof bin momentan strukturiert vor zu gehen. Ich versuchs trotzdem zu lösen.
Ich danke dir tausendfach für deine Hilfe
Zuletzt bearbeitet von Zero01 am 16:15:54 26.01.2012, insgesamt 1-mal bearbeitet
Hat im empfangenen Paket 4 byte Felder zu je 8 Bit. Das erste Byte ist das
niederwertigste, das vierte das höchstwertigste. Man könnte doch angefangen vom niederwertigsten Byte mit bitweise AND bis zum höchstwertigen Verknüpfen um die Ganzzahl int32 zu erhalten. Ist das so Richtig?
void handle_packets( std::vector<char>& Buffer )
{
// Telegrammlänge steht in Bytes 5-8, daher müssen mindestens
// 8 Byte im Puffer stehen while( Buffer.size() >= 8 )
{
// Telegrammlänge bestimmen. unsigned int TelegramLength = Buffer[4] | Buffer[5] << 8 | Buffer[6] << 16 | Buffer[7] << 24;
// stehen genügend Daten im Puffer für das komplette Telegramm? Wenn nein, dann abbrechen if( Buffer.size() < TelegramLength ) return;
Packet Packet;
// Sequence steht in den ersten 4 Byte des Telegramms
Packet.Sequence = Buffer[0] | Buffer[1] << 8 | Buffer[2] << 16 | Buffer[3] << 24;
// Anzahl der Wörter steht in Bytes 9-12 unsigned int WordCount = Buffer[8] | Buffer[9] << 8 | Buffer[10] << 16 | Buffer[11] << 24;
// Zeiger auf Länge des 1. Wortes setzen char* WordPtr = &Buffer[12];
// Wörter isolieren for( unsigned int i = 0; i < WordCount; ++i )
{
// Wortlänge steht in den ersten 4 Bytes unsigned int WordLength = WordPtr[0] | WordPtr[1] << 8 | WordPtr[2] << 16 | WordPtr[3] << 24;
// Inhalt des Strings in Paket einfügen. Inhalt des Strings steht ab Byte 4
// abschließendes Nullbyte ausnutzen, um aus char* einen std::string zu erzeugen
Packet.Words.push_back( WordPtr +4 );
void handle_packets( std::vector<char>& Buffer )
{
// Telegrammlänge steht in Bytes 5-8, daher müssen mindestens
// 8 Byte im Puffer stehen while( Buffer.size() >= 8 )
{
// Telegrammlänge bestimmen. unsigned int TelegramLength = Buffer[4] | Buffer[5] << 8 | Buffer[6] << 16 | Buffer[7] << 24;
// stehen genügend Daten im Puffer für das komplette Telegramm? Wenn nein, dann abbrechen if( Buffer.size() < TelegramLength ) return;
Packet Packet;
// Sequence steht in den ersten 4 Byte des Telegramms
Packet.Sequence = Buffer[0] | Buffer[1] << 8 | Buffer[2] << 16 | Buffer[3] << 24;
// Anzahl der Wörter steht in Bytes 9-12 unsigned int WordCount = Buffer[8] | Buffer[9] << 8 | Buffer[10] << 16 | Buffer[11] << 24;
// Zeiger auf Länge des 1. Wortes setzen char* WordPtr = &Buffer[12];
// Wörter isolieren for( unsigned int i = 0; i < WordCount; ++i )
{
// Wortlänge steht in den ersten 4 Bytes unsigned int WordLength = WordPtr[0] | WordPtr[1] << 8 | WordPtr[2] << 16 | WordPtr[3] << 24;
// Inhalt des Strings in Paket einfügen. Inhalt des Strings steht ab Byte 4
// abschließendes Nullbyte ausnutzen, um aus char* einen std::string zu erzeugen
Packet.Words.push_back( WordPtr +4 );
void handle_packets( std::vector<char>& Buffer )
{
// Telegrammlänge steht in Bytes 5-8, daher müssen mindestens
// 8 Byte im Puffer stehen while( Buffer.size() >= 8 )
{
// Telegrammlänge bestimmen. unsigned int TelegramLength = Buffer[4] | Buffer[5] << 8 | Buffer[6] << 16 | Buffer[7] << 24;
// stehen genügend Daten im Puffer für das komplette Telegramm? Wenn nein, dann abbrechen if( Buffer.size() < TelegramLength ) return;
Packet Packet;
// Sequence steht in den ersten 4 Byte des Telegramms
Packet.Sequence = Buffer[0] | Buffer[1] << 8 | Buffer[2] << 16 | Buffer[3] << 24;
// Anzahl der Wörter steht in Bytes 9-12 unsigned int WordCount = Buffer[8] | Buffer[9] << 8 | Buffer[10] << 16 | Buffer[11] << 24;
// Zeiger auf Länge des 1. Wortes setzen char* WordPtr = &Buffer[12];
// Wörter isolieren for( unsigned int i = 0; i < WordCount; ++i )
{
// Wortlänge steht in den ersten 4 Bytes unsigned int WordLength = WordPtr[0] | WordPtr[1] << 8 | WordPtr[2] << 16 | WordPtr[3] << 24;
// Inhalt des Strings in Paket einfügen. Inhalt des Strings steht ab Byte 4
// abschließendes Nullbyte ausnutzen, um aus char* einen std::string zu erzeugen
Packet.Words.push_back( WordPtr +4 );
Edit:
Ohne Netz und doppelten Boden. Bei kaputten Telegrammen kann dir das um die Ohren fliegen, weil keine Plausibilitätsprüfung für Zeiger gemacht wird.
_________________ 1. Dies ist die erste Regel des Tautologieclubs.
Zuletzt bearbeitet von DocShoe am 18:43:04 26.01.2012, insgesamt 2-mal bearbeitet
Mit dem linksshift war ich ja schonmal nicht ganz so falsch. Auf der rechten Seite des shifts steht die Anzahl N der Bits um die verschoben werden soll...auch noch nachvollziehbar. Ich verstehe das Bitweise OR in seiner Funktion hier einfach nicht
Ich verstehe das Bitweise OR in seiner Funktion hier einfach nicht
Ach, komm´ schon, das ist trivial. Nimm dir´n Blatt Papier und ´nen Stift und mach´ das Ganze ein Mal von Hand. Hier die Wahrheitstabelle für OR, falls das das Problem sein sollte.
Danke Doc hab ein nettes Tutorial zum Thema Bitverschiebung gefunden und weiß jetzt, bezogen auf deine Tips, wie es verwendet wird. Ist im nachhinein auch ne klare Sache wenn ein Wert über mehrere Byte zusammenhängen geschrieben oder gelesen wird. Ich danke dir von ganzem Herzen für deine beispiellose Hilfe. Das Know How durch diesen Thread hat mich ein gutes Stück weiter gebracht
Hey Doc!
ich bin auf ein Problem gestossen. Wenn
die SequenceID 0x00000001 ist dann baue
ich mir doch in den stringstream ungewollt einen wertlosen stringterminator ein (0x00)
You are using std::strings, and ostringstreams, to construct and contain a sequence of bytes. This works as long as you don't try to put any 0x00 bytes into the sequence. Once you start doing so, you are on very shaky ground.
Either the resulting sequence will get cut off at the first 0x00 byte, or mystring.size() will be larger than strlen(mystring.c_str()). That way lies madness and bugs that are difficult to track down.
Besides, you are aware that the 'char' datatype may be either signed or unsigned, depending on which compiler you are using? Normally it is signed. This does not cause any problems for the code that builds the sequence, but may cause problems for the code that decodes a sequence into C++ datastructures.
You are better off using an std::vector<uint8_t> as your container, dropping the ostringstream, and using some custom code for constructing the sequence.
Es trifft hier vor allem nicht zu. Es geht darum, dass std::string durchaus Nullbytes enthalten kann und dass std::string::c_str() einen Zeiger auf einen linearen Puffer des Stringinhalts zurückgibt. Damit kommen die C-Funktionen natürlich nicht klar, aber wer Konstruktionen wie
C/C++ Code:
std::string s = "Mächtiger Badabumm";
unsigned int len = strlen( s.c_str() );
C/C++ Code:
std::string s = "Mächtiger Badabumm";
unsigned int len = strlen( s.c_str() );
C/C++ Code:
std::string s = "Mächtiger Badabumm";
unsigned int len = strlen( s.c_str() );
benutzt hat eh´ nicht mehr alle Latten am Zaun. Du solltest inzwischen gemerkt haben, dass man genau wissen muss, was man programmiert. Wenn du C++ und C Funktionen so mischst, dass Fehler entstehen, dann weißt du´s offensichtlich gerade nicht.
In dem ganzen Code, den ich hier gepostet habe, tritt der Fall nie auf. Wie kommst du also darauf?
_________________ 1. Dies ist die erste Regel des Tautologieclubs.
Zuletzt bearbeitet von DocShoe am 18:37:43 01.02.2012, insgesamt 1-mal bearbeitet
Hmmm, ich frage mich gerade warum dieser
negative Unterton. Ich habe doch nur
freundlich eine Frage gestellt, zahle
meine Steuern pünktlich und tuhe auch
sonst keiner Fliege was zu leide.
Ich wurde in einem Forum von einem
User gefragt, ob ich ein C++ Beispiel habe
um ein Paket mit den gegebenen Anforderungen zu erstellen. Als
Beispiel habe ich ihm deinen
unveränderten Code gezeigt ohne
includes und ohne main().
Daraufhin hat sich einer der
Chefentwickler von EA Games
mit dem oben genannten Statement
geäussert. Daraufhin fühlte ich
mich verunsichert und wollte
dich nochmal Fragen, Gott verzeihe.
Ich hab jetzt einen Testcode aufgebaut um sein Statement nachzubilden. Resultat des ganzen ist, dass ich seine Befürchtung mit 0x00 in einem String egal welcher Art theoretisch nachvollziehen kann aber in der Praxis mit deinem Code vollkommen irrelevant ist.
That bit right there takes a 32-byte integer, splits it up into 4 bytes, and stuffs each of the 4 bytes into an ostringstream object. Raw. So if Sequence == 0x00000001, the code will be stuffing 0x00's into the ostringstream.
std::string kann mit Nullbytes umgehen und wird auch so verwendet. Auch in gängiger C++ Fachliteratur (z.B. Scott Meyers) steht nichts darüber, dass man das nicht tun soll.
Was dieser angebliche "Chefprogrammierer" da schreibt:
Zero01 schrieb:
Both these code sections violate the principle: do not stuff 0x00s into strings.
ist eine hausinterne Regel, die jemand braucht, der so etwas wie
C/C++ Code:
unsigned int len = strlen( s.c_str() );
C/C++ Code:
unsigned int len = strlen( s.c_str() );
C/C++ Code:
unsigned int len = strlen( s.c_str() );
schreibt.
Dass der, wie DocShoe schreibt, nicht alle Latten am Zaun hat, ist Realität und kein negativer Unterton.
Auch C-Strings können Nullbytes enthalten:
C/C++ Code:
char* pc = "ABC\0abc";
C/C++ Code:
char* pc = "ABC\0abc";
C/C++ Code:
char* pc = "ABC\0abc";
Es gibt genügend Anwendungen, wo das vorkommt. Was mach der "Chefprogrammierer" dann ?
Zuletzt bearbeitet von nn am 10:15:46 02.02.2012, insgesamt 2-mal bearbeitet
Jetzt fühl´ dich nicht gleich auf den Schlips getreten, ich habe weder behauptet, dass du Steuern hinterziehst noch irgendwie anders kriminell bist.
C++ ist nun mal ein Sprache, die Vieles erlaubt und damit auch viele Möglichkeiten bietet, etwas falsch zu machen. Deshalb schrieb ich ja schon mehrmals, dass man genau wissen muss, was man tut. Wenn ich weiß, dass eine Sequence Binärdaten enthält, dann sollte ich da kein strlen draufloslassen, weil eben genau der Fall eintreten kann, dass irgendwo mittendrin Nullbytes stehen. Und dann liefert strlen nicht das zurück, was man haben will. Für jedes Problem das richtige Werkzeug, und in diesem Fall ist strlennicht das richtige Werkzeug. Im übrigen geht
C/C++ Code:
std::vector<uint_8t> MyVec = ...;
unsigned int len = strlen( &MyVec[0] );
C/C++ Code:
std::vector<uint_8t> MyVec = ...;
unsigned int len = strlen( &MyVec[0] );
C/C++ Code:
std::vector<uint_8t> MyVec = ...;
unsigned int len = strlen( &MyVec[0] );
genauso in die Hose, wenn der Vektor Nullbytes in der Mitte enthält.
Der EA Chefprogrammierer assoziiert mit std::string wohl ein gekapseltes C-String Pendant. Dabei ist std::string wesentlich mächtiger als C-Strings, und das habe ich in meinem Code bewusst ausgenutzt. Du kannst stattdessen natürlich auch einen std::vector<unsigned char> benutzen, wenn es dir besser gefällt:
aber da gefällt mir das ostream Interface wesentlich besser.
Mit gleichem Argument könnte ich die Benutzung von iteratoren verbieten, da dieser Code zwar kompiliert, aber zu UB führt, was ziemlich knifflig zu debuggen ist:
C/C++ Code:
std::vector<int> v =...;
std::sort( v.end(), v.begin() );
C/C++ Code:
std::vector<int> v =...;
std::sort( v.end(), v.begin() );
C/C++ Code:
std::vector<int> v =...;
std::sort( v.end(), v.begin() );
_________________ 1. Dies ist die erste Regel des Tautologieclubs.
Zuletzt bearbeitet von DocShoe am 10:59:55 02.02.2012, insgesamt 1-mal bearbeitet
Danke Jungs für die Aufklärung. Jetzt
wo ich dagegen argumentiert habe, hüllt
sich dieser Mensch in schweigen.
Die Aufruf um den std::string als
konstanten c_string zu lesen
um die strlen zu bestimmen is eh unfug.
Wofür haben wir dann das Bordmittel
.size() was keinerlei Sprachvermischung
benötigt.
Danke Jungs für die Aufklärung. Jetzt
wo ich dagegen argumentiert habe, hüllt
sich dieser Mensch in schweigen.
Die Aufruf um den std::string als
konstanten c_string zu lesen
um die strlen zu bestimmen is eh unfug.
Wofür haben wir dann das Bordmittel
.size() was keinerlei Sprachvermischung
benötigt.
Nächstes Thema anzeigen Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben. Sie können auf Beiträge in diesem Forum antworten. Sie können Ihre Beiträge in diesem Forum nicht bearbeiten. Sie können Ihre Beiträge in diesem Forum nicht löschen. Sie können an Umfragen in diesem Forum nicht mitmachen.
c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums
für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de
Werbekostenerstattung verdient werden kann.
Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info, www.c-sar.de, www.c-plusplus.net und www.baeckmann.de
enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt
(vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in
privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden.
Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere
übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.