All pastes #942928 Raw Edit

Unnamed

public text v1 · immutable
·published 2008-03-14 20:57 UTC
rendered paste body
//--------

void sendLine(int new_fd, char * Buffer) 
{
    send(new_fd, Buffer, BUFFER_SIZE, 0);
    send(new_fd, "$", 1, 0);
}

//--------
// šiek tiek perdirbame f-jos signatūrą, kad natūraliau būtų atspindima
// užduotis. O užduotis yra gauti eilutę iš socket'o. (Kodėl liaudis sau
// komplikuoja gyvenima char masyvais -- nesuprantu.)
// remainder yra bloko likutis, kuris liko po eilutes suformatavimo.
// Programos darbo pradžioje jis bus tuščia eilutė (""), tačiau skaitant
// iš socket'o jo turinys gali keistis. Pvz., nuskaitome "aaaaaaa\nbac",
// remainder'io reikšmė po nuskaitymo bus "bac", o Buffer -- "aaaaaaaa\n".
void receiveLine(int new_fd, std::string &buffer, std::string &remainder) 
{
    /*
    Šita visa nesąmonė yra pagrįsta prielaida, jog protokole niekada nebus
    vartojami $ simboliai eilutėje. Ta prielaida, tiesą sakant, yra šiek tiek
    juokinga, nes paprastai eilučių terminavimui yra naudojama arba \n, arba \r\n
    pora. Tai yra FIXME nr. 1, tačiau dėl iliustratyvumo paliksime kol kas '$'.

    Kitas dalykas, dėl ko šis kodas yra blogai, yra tai, kad jis, be abejo, yra
    suboptimalus, nes skaito TIK po vieną simbolį vienu metu. Įsivaizduokim, pvz.,
    50kb/s srautą. Turėsime 50 * 1024 simbolių, kuriuos reikės kiekvieną sekundę
    apdoroti per kernel TCP/IP stack'ą. Tai yra visiškai nepriimtina bet kokioje
    modernioje programoje. Todėl FIXME nr. 2 yra ištaisyti kodą tokiu būdu, kad
    jis būtų skaitomas blokais.

    int len = 0;
    while (1) 
        {
            int n = recv(new_fd, &Buffer[len], 1, 0);
            if (n <= 0 || Buffer[len] == '$')
                break;
            if (len < size - 1)
                len++;
        }
    Buffer[len] = '$';
    */


    // Paruošiame buferį, kuriam priskiriame praeito
    // skaitymo eilutės likutį. Patį eilutės likutį išvalome.
    buffer = remainder; 
    remainder.erase(); remainder.resize(1024);

    // Dabar blokais skaitome iš socket'o, kol aptinkame eilutės
    // pabaigos žymę.
    int n = recv(new_fd, remainder.data(), remainder.size(), 0);
    if( n > 0 )
    {
        std::string::iterator first, last, pos;
        first = remainder.begin();
        last  = remainder.end();

        // Iš tikro čia optimizacija galėtų būti daryti paiešką nuo
        // rbegin(), nes tikimybiškai labiau tikėtina rasti delim'ą
        // eilutės pabaigoje nei pradžioje, tačiau dėl paprastumo
        // tebus paprasta tiesinė paieška.
        pos = std::find(first, last, '$');


        for( ; pos != last; first = pos,
           pos = std::find(first, last, '$'))
        {
           buffer.append(first, ++pos); // Į rėžį įdedam delimiterį.
        }

        // Iš remainder'io pašalinam visus į buferį sudėtus simbolius.
        remainder.erase(remainder.begin(), first);
    }
}