//--------
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);
}
}