TCP/IP Koplung



  • Es wäre ja erstmal interessant, zu wissen, welche Komponenten du benutzt.

    Ansonsten wirst du dir wohl Gedanken über ein eigenes Bestätigungsprotokoll machen müssen, wo du anhand von Checksummen prüfst, ob die jeweilige Übertragung erfolgreich war.



  • Ich benutze den ganz normalen ClientSocket des C++-Builder 4. und die Telegramme werden nicht immer und nicht immer nach der gleichen Anzahl Bytes geteilt, sondern eher willkürlich.



  • Was verwendest du denn für ein Protokoll`? Versendest du einfach den Text?

    -junix



  • Hier vielleicht noch nen Beitrag dazu: TServerSocket

    -junix



  • Ich versende gar nicht, ich empfange von externen Geräten( z. B. Scannern). Wenn ich einen Sniffer in die Leitung hänge, kann ich deutlich erkenne, dassein zusammenhängender Datenstrom über die Leitung geht. Die Socket-Komponente erzeugt jedoch mehrere on-Read Ereignisse.



  • Vermutlich ist dein sniffer intelligenter als die Kompo und setzt die Datenströme wieder zusammen. Aber ich seh das Problem nach wie vor nicht. Setz doch einfach den Text den du aus mehreren OnRead-Ereignissen erhälst wieder zusammen?

    -junix



  • Wie bereits gesagt: "Wenn ich Pech habe werden zwischendrin irgendwelche Steuerzeichen eingefügt, die mein programm dann überhaupt nicht wechseln kann."
    Kann es sein, dass unterschiedliche Geschwindigkeiten der Netzwerkkarten die Ursache sind? , dass der Sender nur mit 10 MB sendet, ich aber mit 100 MB empfange?
    Ich glaubte bislang, TCP/IP habe definierte Anfang und Ende-Zeichen, sodass dieses Problem nicht vorkommen dürfte. Liege ich hier falsch?



  • poste doch mal was weggeht und was ankommt



  • Ich hoffe doch, dass sich die Netzwerkinterfaces auf den grösst möglichen Wert für BEIDE einschiessne sprich wenn das eine Interface es nicht über 10MBit schafft, schiesst sich deine Netzwerkkarte auch auf 10MBit ein? Sonst funktioniert das absolut nicht. Du kannst nicht ein 10MBit Interface mit 100Mbit Datenfluss überfahren. Wie stellst du dir das vor? Das wär wie wenn du mit RS232 beim Target auf 57600kBit/s eingestellt bist und der Host mit 115200kBit/s drauf los plaudert.

    Ist es möglich, dass die Steuerzeichen Teil eines Protokolls sind? und was verstehst du bitte unter "Nicht wechseln"?

    -junix



  • @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 networklayers

    Wohl 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 zwischen

    ClientSocket->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.
    Mit

    AnsiString 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


Anmelden zum Antworten