socket 4096 bytes auf einmal senden, aber weniger auf der anderen seite auslesen



  • Also mit Linux scheint es jetzt zu funktionieren, jedoch ist MSG_WAITALL unter Windows (Visual C++ 6.0) nicht definiert obwohl http://msdn2.microsoft.com/en-us/library/ms740121.aspx was anderes sagt und ich eigentlich Winsock2.h benutze.

    Kann mir da vielleicht jemand weiterhelfen?

    Danke im Voraus!

    Rainer



  • ruf recv in einer schleife auf



  • das problem ist dass ich genau die blöcke in fester größe brauche und wenn ich dieses flag da nicht setzen kann, dann bekomme ich nur so viel wie grad vorhanden ist und nicht den ganzen puffer gefüllt.



  • das flag gibt es anscheinend erst ab einer bestimmten windows version. im header steht:

    #if(_WIN32_WINNT >= 0x0502)
    #define MSG_WAITALL     0x8             /* do not complete until packet is completely filled */
    #endif //(_WIN32_WINNT >= 0x0502)
    

    also _WIN32_WINNT größer oder gleich 0x0502 definieren bevor du die header includierst. sollte das nicht funktionieren besorg dir ein neueres platform sdk oder kopier dir die definition einfach von hier.

    aber lass es lieber und programmier das verhalten selbst



  • rainerhaussmann schrieb:

    das problem ist dass ich genau die blöcke in fester größe brauche und wenn ich dieses flag da nicht setzen kann, dann bekomme ich nur so viel wie grad vorhanden ist und nicht den ganzen puffer gefüllt.

    Run recv in einer Schleife auf und schreibe dabei in die Blöcke fester Größe (natürlich ab der Position wo er beim letzten Lesen beendet hat). Wo ist das Problem dabei?



  • das problem ist dass das einlesen der daten über mehrere funktionen verteilt ist und deshalb sowas mit halbwegs vernünftigem aufwand nicht zu machen ist.

    danke aber für den tipp, weil generell ist das ja ne gute idee.



  • Versteh ich nicht. Du müsstest doch einfach jedes recv durch dein eigenes "recv_all" ersetzen. Was ist daran aufwendig? MSG_WAITALL müssteste doch auch überall hin machen?



  • hmm stimmt eigentlich, ich hab eine eigene recv() funktion geschrieben, in dieser könnte ich das eigentlich einbauen 🙂



  • hier mal ein beispiel, allerdings für nonblocking sockets.
    dürfte leicht umzubauen sein, überflüssiges zeug rausschmeissen, usw...

    static int RC_recv_all (SOCKET sock, char *buff, unsigned short size)
    {
        DWORD timeout = GetTickCount() + 5000;
    
        while (size)
        {
            int res = recv (sock, buff, size, 0);
            // Connection closed? --> exit
            if (res == 0)
                return -1;
            // recv failed?
            else if (res == SOCKET_ERROR)
            {
                // No data?
                if (WSAGetLastError() == WSAEWOULDBLOCK)
                {
                    // Timed out --> exit
                    if (timeout < GetTickCount())
                        return -1;
                    // Retry
                    Sleep(10);
                    continue;
                }
                // Any other error --> exit
                return -1;
            }
            // Rx next chunk
            size -= res;
            buff += res;
        }
    
        // All Rx'd
        return 0;
    }
    

    🙂



  • Es gibt keine Blöcke bei TCP, das ist ein Bytestrom. Es gibt nur den Anschein von Blöcken, weil TCP natürlich auf ein paketorientiertes Protokoll aufsetzt. Aber es gibt auf TCP-Ebene keine Möglichkeit, da irgendwas zu beeinflussen, es gibt auch keine sinnvollen Erwartungen an die Größe, die recv mit einmal liest. Das ist so gewollt und gut so, und du tätest besser daran, deinen Ansatz zu überdenken, als mit Gewalt einen weiteren Beitrag zu www.thedailywtf.com zu liefern.



  • mein vorschlag wäre, definier dir ein blockanfang (irgend ne kombination aus 4 byte oder so) danach hängdt du einfach 1 byte für die länge an, du sendest also praktisch einen strom aus 4byte start 1byte länge rest daten

    für den empfang nimmst du ne statemachine, state ready, state moredata, state data_arrived.

    du wartest einfach das mind. 5 byte ankommen, also blockstart und länge,
    wechselst in den status moredata.

    dort wartest du mit MSG_PEEK als flag ab bis "len" byte oder mehr vorhanden sind.
    dann rufst du recv auf in einen beliebig großen puffer
    (ein statischer puffer von 255 reicht wenn du nur 1 byte für die länge benutzt)
    ABER als l-wert bei recv gibst du NUR den len-wert an den du nach deinem blockstart ausgelesen hast, wertest das "paket" aus und fängst wieder bei start an

    (das iss nur ne idee also nich hauen, habs selber SO noch nicht probiert)

    by the way könnte man nicht das UDP-protokoll dafür vergewaltigen ?

    NOCHN EDIT das mit dem blockstart dient nur falls du mal nen fehler hast und den nächsten blockanfang suchst ansonsten kannst dich ja blauäugig drauf verlassen das jedes erste byte die länge iss ud einfach den blockstart weglassen



  • danke euch, ich hoffe dass ich das jetzt hinbekomme 🙂


Anmelden zum Antworten