Sender store data > 1 MB gennem Windows Sockets viz ved hjælp af Send-funktionen

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg søger at sende en stor besked> 1 MB gennem Windows-stikkene, send api. Er der en effektiv måde at gøre dette på, vil jeg ikke løkke og derefter sende dataene i klumper. Jeg har læst et sted, hvor du kan øge socket buffer størrelse og det kunne hjælpe. Kan nogen venligst uddybe dette. Enhver hjælp er værdsat

Bedste reference


Du skal, og faktisk skal løkke for at sende dataene i stykker.


Som forklaret i Beejs netværksvejledning:



  'send () returnerer antallet af bytes, der faktisk er sendt ud - dette kan være mindre end det nummer, du fortalte det at sende! Se, nogle gange siger du det til at sende en hel del data og det kan bare ikke håndtere det. Det 'slukker så meget af dataene som muligt, og stoler på at du sender resten senere.'



Dette indebærer, at selvom du sætter pakkestørrelsen til 1 MB, sender funktionen send () muligvis ikke alle, og du er nødt til at løbe, indtil det samlede antal bytes, der sendes af dine opkald til at sende () i alt antal bytes du forsøger at sende. Faktisk, jo større pakken er, jo mere sandsynligt er det, at send () ikke sender det hele.


Bortset fra alt det, vil du ikke sende 1MB-pakker, fordi hvis de går tabt, skal du sende hele 1MB-pakken igen, mens hvis du taber en 1K-pakke, er det ikke meget at sende det igen.


Sammenfattende skal du slække dine send () opkald, og modtageren skal endda slække deres recv () opkald også. Du skal sandsynligvis lægge en lille overskrift til hver pakke for at fortælle modtageren, hvor mange byte der skal sendes, så modtageren kan løbe det passende antal gange.


Jeg foreslår, at du kigger på Beejs netværksguide for mere detaljeret information om send () og recv () og hvordan man kan håndtere dette problem. Det findes på http://beej.us/guide/bgnet/output/print/bgnet\_USLetter.pdf[2]

Andre referencer 1


Hvorfor vil du ikke sende det i stykker?


Det er den måde at gøre det i 99\% af sagerne.

Andre referencer 2


Windows sockets subsystem er ikke oblidged for at sende hele bufferen du giver alligevel. Du kan ikke tvinge det, da nogle netværksprotokoller har en øvre grænse for pakkestørrelsen.

Andre referencer 3


Hvad får dig til at tro, at indsendelse af bidder er ineffektivt? OS'et vil sandsynligvis chunk store 'send' opkald alligevel, og kan sammenblande små.


Ligeledes på modtagersiden skal klienten løbe alligevel, da der ikke er garanti for at få alle dataene på én gang.

Andre referencer 4


Som et praktisk spørgsmål kan du faktisk allokere en stor buffer og sende ét opkald vha. Winsock. Hvis du ikke røber med socketbufferstørrelser, bliver bufferen generelt kopieret til kernel-tilstand for at sende i alligevel.


Der er en teoretisk mulighed for, at den vil vende tilbage uden at sende alt, så du skal virkelig løbe for korrekthed. De stykker, du sender, skal dog være store (64k eller ballpark) for at undgå gentagne kernelovergange.

Andre referencer 5


Hvis du vil lave en sløjfe, kan du bruge denne C ++ kode:


#define DEFAULT\_BUFLEN 1452    
int SendStr(const SOCKET &ConnectSocket, const std::string &str, int strlen){
        char sndbuf[DEFAULT\_BUFLEN];
        int sndbuflen = DEFAULT\_BUFLEN;
        int iResult;
        int count = 0;
        int len;
        while(count < strlen){
            len = min(strlen-count, sndbuflen);
            //void * memcpy ( void * destination, const void * source, size\_t num );
            memcpy(sndbuf,str.data()+count,len);
            // Send a buffer
            iResult = send(ConnectSocket, sndbuf, len, 0);
            // iResult: Bytes sent
            if (iResult == SOCKET\_ERROR){
                throw WSAGetLastError();
            }
            else{
                if(iResult > 0){
                    count+=iResult;
                }
                else{
                    break;
                }
            }
        }
        return count;
    }