TCP/IP Koplung
-
@junix ich glaub die geschwindigkeit ist sache des networklayers, bisher reden wir nur über transportlayer, demnach müsste sich doch jemand anders (nic-treiber) um die geschwindigkeit kümmern, oder bin ich total aufm falschen dampfer?
-
NIcht wechseln soll heißen, daß ich diese Zeichen nicht abfrage und da bei deren auftreten auch die Telegrammlänge nicht stimmt, sodaß ich dieses Telegramm ignoriere. Die Steuerzeichen sind nicht Bestandteil der Nutzdaten. Sie entstehen durch irgendwie durch das Zerstückeln der Telegramme. Es werden nur Ascii-Zeichen gesendet.
-
Original erstellt von DBler:
ich glaub die geschwindigkeit ist sache des networklayersWohl eher des Physical Layers (-; Aber ich hab ja auch nicht damit angefangen sondern Mecki (:
@Mecki: Zeig mal die Steuerzeichen und bitte Zeig mal was gesendet und was empfangen wird.
Die Variablen sind alle sauber initialisiert? Die Daten empfängst du also wirklich beim OnRead?
-junix
-
@junix:
Besten Dank für Dein Interesse an diesem Problem !!
Der Anfang meiner OnRead Routine sieht folgendermaßen aus:void __fastcall TfrmMain::ClientSocket_ScannerRead(TObject *Sender, TCustomWinSocket *Socket) { AnsiString asTemp, asTele, asTemp1; AnsiString asBarcode,asHerkunft,asZiel,asScanNum,asHoehe; Telegrammstruktur Telegramm; int k, Laenge, iScanNum; bool bNoRead = false; char Feld[512]; k= strlen(Feld); // Leeren for (int l=0; l < k; l++) { Feld[l]= 0x00; } Laenge= frmMain->ClientSocket_Scanner->Socket->ReceiveLength(); frmMain->ClientSocket_Scanner->Socket->ReceiveBuf(Feld, Laenge); // empfangene Daten zwischenspeichern Laenge= strlen(Feld); Feld[Laenge]= 0x00; // Endezeichen setzen AnsiString asTest = Feld; MeldungsProtokoll("ScannerSocket_Read angekommen Laenge =" + AnsiString(Laenge)); // Meldung in Spooler Datei MeldungsProtokoll("Inhalt =" + asTest); asTemp= Feld; // Empfangenes Telegramm MeldungsProtokoll("empfangenes Telegramm "+asTemp); // Meldung in Spooler Datei
Zu den Steuerzeichen kann ich nur sagen, daß es sich um irgendwelche nicht-ascii-Zeichen gehandelt hat und daß sie nicht reproduzierbar waren. Die Routine Meldungsprotokoll, die Du im Code siehst schreibt einfach zur Kontrolle in eine .txt-Datei, da die Phänomene nur im Echtzeitbetrieb getestet werden können.
<edit>Bitte Code-Tags verwenden!</edit>
[ Dieser Beitrag wurde am 19.02.2003 um 08:54 Uhr von junix editiert. ]
-
Original erstellt von Mecki:
Besten Dank für Dein Interesse an diesem Problem !!Kein problem... interessiert mich grad und ich spiel sowieso gern mit TCP/IP (:
Zu den Steuerzeichen kann ich nur sagen, daß es sich um irgendwelche nicht-ascii-Zeichen gehandelt hat und daß sie nicht reproduzierbar waren.
Es sind bestimmt ASCII, aber vielleicht keine druckbaren Zeichen. es wär sehr interessant, welchen Hexwert die Teiler haben. (Schreib den Datenstrom binär in die datei und öffne Sie mit dem Hexeditor.)
Jetzt zu deinem Code:
char Feld[512];
Ich würde dir emfpehlen, dieses Char-Array dynamisch zu erstellen (new) auf Basis des durch RecieveLength() erhaltenen Werts. (aber auf keinen Fall das delete [] vergessen)
k= strlen(Feld); // Leeren for (int l=0; l < k; l++) { Feld[l]= 0x00; }
Den ganzen Klimbim hier kannst du mit der Funktion memset() erschlagen (sollte nach jedem neuen allozieren eines Speicherbereichs erfolgen um einen definierten Zustand herzustellen (z.B. eben alle Charakter auf 0x00 zu setzen).
Laenge= frmMain->ClientSocket_Scanner->Socket->ReceiveLength(); frmMain->ClientSocket_Scanner->Socket->ReceiveBuf(Feld, Laenge); // empfangene Daten zwischenspeichern
Zwei Dinge: 1. OnRead() liefert dir den Zeiger auf den Socket der den Event ausgelöst hat selber mit (Siehe Parameter socket) und ich empfehle dir diesen Parameter zu benutzen (dann ersparst du dir auch den ganze Rattenschwanz von frmMain bis ClientSocket_Scanner....
2. Wenn du dir die Methoden von TCustomWinSocket (der Typ des Propertys "Socket") anschaust findest du eine Methode "RecieveText()" wenn du eh nur Text-Daten und nix binäres empfangen willst würde ich dir diese Methode ans Herz legen. (dann ersparst du dir das ganze Handling mit dem char-array...)Mein ganz persönlicher verdacht ist der, dass die Datenlänge eventuell manchmal GENAU (oder mehr als) 512-byte ist. damit wird das abschliessende Null überschrieben. Bei der Zuweisung in den AnsiString wird dann alles bis zum nächsten 0x00 zugewiesen. (inklusive irgendwelchem trash).
-junix
-
Dein "Persönlicher Verdacht" ist mit Sicherheit falsch, da immer nur 18 bis 20 Byte ankommen. Ich habe mir jetzt die Protokolldatei 'mal mit dem HexEditor angesehen: Die Steuerzeichen, die ja nur sporadisch auftreten sind 06Hex und 15Hex.
Das beantwortet jedoch noch immer nicht die Frage, warum manche Telegramme überhaupt zerstückelt im Buffer ankommen.
-
Original erstellt von Mecki:
Das beantwortet jedoch noch immer nicht die Frage, warum manche Telegramme überhaupt zerstückelt im Buffer ankommen.... Das muss nicht zwingend an einem fehlerhaften frame liegen. Es kann durchaus auch sein, dass das event schneller verarbeitet ist, als das ganze Frame ankommt. Ich würde trotzdem mal auf dynamisches Erstellen von Puffern umstellen ... ist der Sender von einem 3. Hersteller oder besteht die Möglichkeit dass da fehler drin sind?
-junix
-
Der Sender ist in diesem Fall eine Etikettiermaschine. Ich habe das gleiche Problem aber auch mit einem Scannernetzwerk und Waagen, die über einen W&T-ComServer angeschlossen sind.
Mir ist da noch eine Idee gekommen: Wann bekomme ich das OnRead-Ereignis eigentlich? wenn das erste Byte im Buffer eingetroffen ist oder das letzte?
Mein neuester Verdacht: Kann es sein, das das Event bereits beim Eintreffen des ersten Zeichens kommt und meine Rechner so schnell ist, das ich schon vorm Eintreffen des letzten Zeichens den Buffer ausgelesen habe ??
Dazu gleich noch 'ne Frage: Wo liegt eigentlich der Unterschied zwischenClientSocket->Socket->ReceiveBuf(Buffer, Laenge);
und
AnsiString Buffer = ClientSocket->Socket->ReceiveText();
Ist es wirklich nur der Parameter ??
-
Mit
ClientSocket->Socket->ReceiveBuf(Buffer, Laenge);
kannst du auch binäre Daten empfangen, also z.B. Bilder.
MitAnsiString Buffer = ClientSocket->Socket->ReceiveText();
bist du nur in der Lage, Strings bzw. Textdaten zu empfangen.
-
Original erstellt von Mecki:
Wann bekomme ich das OnRead-Ereignis eigentlich? wenn das erste Byte im Buffer eingetroffen ist oder das letzte?Ich habe diesen Verdacht ja oben auch erwähnt... Ich hab bei einem kurzen Streifzug durch die Hilfe keine bestätigenden INformationen gefunden aber alleine schon aus der Logik dass der Client-Socket nicht weiss wann die Daten fertig sind, dürfte er wohl den Event nach dem ersten empfangenen Byte auslösen...
-junix