send/recv



  • Danke für Eure Antworten.

    @Merano
    sizeof(data) liefert auf sowohl auf dem Sever wie auch auf dem Client die gleiche Größe. Ich denke sonst würde das Client Binary auch unter Windows 7 versagen.

    @Softwaremaker
    Ich schaue mir den verlinkten Teil mal an. Da muß ich mal schauen wie man den Empfangspuffer anpassen kann.

    @Dingsbums
    Im Prinzip hast Du schon recht, data ist jedoch eine struct mit floats und ints. Da ist es nicht so einfach aus dem Datenstrom den Anfang und das Ende zu finden.



  • Hi,

    Egal was Du sendest, es ist jederzeit möglich das dein TCP Packet in mehrere Teile zerlegt wird, somit kommst Du mit einem read grundsätzlich nicht aus.

    Sende als Header deiner Daten die zu erwartende Länge, der client muss also solange lesen bis diese Länge erreicht ist um sicher zustellen das ein synchron block ab Size in eine Struct gelesen worden ist.

    Grüße und Erfolg
    Karsten



  • @Achromat

    Warum die länge der Daten denn noch mal in einem Header übertragen? das wird doch schon eine ebene darunter gemacht, man muss doch nur so lange lesen bis keine daten mehr verfügbar sind. Das ist eigentlich auch das normale vorgehen weil man ja eh nicht sagen kann wie groß die Daten sind und wenn ich 100MB rüber schieben will dann wird auch Windows 7 oder Windows 8 oder was auch immer da die weisse Fahne heben und sagen nö das kann ich net in einem rutsch übertragen, also warum erst so einen umstand machen, TCP ist doch dafür da das die Daten im gesammten und in der richtigen reighenfolge übertragen werden warum das fahrrad noch einmal eine ebene höher neu erfinden?



  • CTecS schrieb:

    @Achromat

    Warum die länge der Daten denn noch mal in einem Header übertragen?

    Weil du auf das was der TCP/IP Stack intern macht kaum Einfluss hast, und auch an die Daten nicht drankommst.
    Das System ist einfach nicht darauf ausgelegt dass eine höhere Schicht auf einzelne TCP/IP Pakete zugreift. Nach oben ist es einfach ein Stream.

    CTecS schrieb:

    das wird doch schon eine ebene darunter gemacht, man muss doch nur so lange lesen bis keine daten mehr verfügbar sind.

    Und woher weisst du wann "keine Daten mehr verfügbar sind"? Wenn 100ms nix mehr kommt? Eine Sekunde? 10 Sekunden?

    CTecS schrieb:

    Das ist eigentlich auch das normale vorgehen weil man ja eh nicht sagen kann wie groß die Daten sind und wenn ich 100MB rüber schieben will dann wird auch Windows 7 oder Windows 8 oder was auch immer da die weisse Fahne heben und sagen nö das kann ich net in einem rutsch übertragen, also warum erst so einen umstand machen, TCP ist doch dafür da das die Daten im gesammten und in der richtigen reighenfolge übertragen werden warum das fahrrad noch einmal eine ebene höher neu erfinden?

    Hä?
    Ja, TCP/IP ist dafür da. D.h. natürlich kannst du mit einem einzigen send() Aufruf 100 MB auf einmal übertragen - gar kein Problem. Der TCP/IP Stack zerteilt dir das automatisch in passende Pakete, und die werden dann übertragen. Inklusive Fehlertoleranz etc.
    Und nochmal: nach oben, also aus Sicht deiner Applikation, ist TCP/IP ein Stream-Protokoll. Da gibt's keine "Blöcke" oder ähnliches. Und es gibt auch kein "keine daten mehr verfügbar" -- denn woher soll der TCP/IP Stack wissen dass eine Applikation keine weiteren Daten mehr schicken wird bis die andere Seite geantwortet hat.

    Die einzige Möglichkeit die es hier gibt ist eine Verbindung einseitig zu schliessen. Damit sagst du dem Stack "ich werde keine weiteren Daten schicken". Das ist aber nicht reversibel, d.h. du kannst danach auf dieser Verbindung überhaupt keine Daten mehr schicken.

    => Du musst dich selbst darum kümmern dass der Empfänger wissen kann wo ein Datenblock aus ist.

    ps: Und das ist auch nicht "das Fahrrad noch einmal eine Ebene höher neu erfinden", denn sowas wie "Messages" kennt TCP/IP nicht. Es gibt bloss die sog. "Transmission Units". Für diese gibt's allerdings ein (verbindungsabhängiges!) Grössen-Limit, und die Applikation hat auch keine Kontrolle darüber wie die Daten in "Transmission Units" aufgeteilt wird. Beides Gründe die es unmöglich machen Application-Messages 1:1 auf "Transmission Units" abzubilden.



  • Ist garnicht so wild, es ist natürlich nötig in einem thread die Daten zu erheben, und immer wenn eine Size gelesen ist, legst Du ein Signal an, das den Zugriff auf den Lesespeicher so triggert, das nicht gleichzeitig drauf zugegriffen werden kann:

    Pseudo:

    int CMySock::Receive(char *pMem,int Size)
    {
    	int iLen(0),cnt(0);
    
    	 while(((iLen += (cnt = recv(m_sock, (char *)(pMem+iLen), Size, 0))) < Size) && cnt > 0);
    
    	 m_BytesReceive+=iLen;
    
    	return iLen;
    }
    

    Liefert recv == 0 sind keine Daten beim lauschen angefallen, natürlich lässt Du Sock::recv im blocked mode laufen(default), so kommt die Methode auch gar nicht erst zurück wenn keine Daten vorliegen. Liefert es < 0 , ist die Verbindung getrennt worden.

    Wenn Du nicht weißt vieviel das größte "wiegt" das kommen kann via recv, dann musst Du das vorher erfragen mit :

    int len(sizeof(int)), DatMax(0);
        getsockopt(m_sock,SOL_SOCKET,SO_RCVBUF,(char *)&DatMax,&len);
    

    Wenn Du ganz verwegen bist, kannst du auf die Hardwareeigenschaft deiner Netzwerkkarte gehen, und dort Jumbo Packet Size aktivieren, wenn dein Sock geöffnet ist kannst Du mit :

    int DataGranuar = 4000000;
        if(setsockopt(m_sock,SOL_SOCKET,SO_RCVBUF,(char *)&DataGranuar,sizeof(int)) == SOCKET_ERROR)
    	 return false;
    

    Bestimmen das Du nun riesen Klamotten in einem Zug empfangen möchtest, was natürlich nicht vor Zerteilung schützt, aber so ggf, mehr performance erzeugt z.b. Bei Bildertransfer, dann werden aber andere Anwendungen kaum mehr Daten durch bekommen !

    Gruß
    Karsten



  • Achromat schrieb:

    int CMySock::Receive(char *pMem,int Size)
    {
    	int iLen(0),cnt(0);
    
    	 while(((iLen += (cnt = recv(m_sock, (char *)(pMem+iLen), Size, 0))) < Size) && cnt > 0);
    
    	 m_BytesReceive+=iLen;
    
    	return iLen;
    }
    

    Versuchst du absichtlich Code so zu schreiben dass er quasi unlesbar ist?
    Davon abgesehen hast du da mMn. mindestens zwei bzw. drei grobe Fehler drinnen (kommt drauf an was man als "eigenen" Fehler rechnet).



  • Dann erzähl mal was, zu den 3 Verstößen ^^



  • Finde sie selber.
    Tip: dazu ist es hilfreich wenn du erstmal die while Schleife so hinschreibst dass man einfach lesen/sehen kann was in welchen Fall und in welcher Reihenfolge alles gemacht wird.



  • beklagen tun sich jene über Strecken, die im Wesen schon verrecken.



  • lol


Anmelden zum Antworten