Lenne a adatfolyamat mely így nézne ki <0000;01234;A;DATA;TYPE> az adat lehet bármilyen hosszú, és a típus is ami pl.: UTF-8
Ezt hogy lehetne hatékonyan olvasni c vagy c++ -ban egy tcp session-ből, mert ugyebár változó hosszú az egész és hibát is észre kéne venni, ha van benne.
igazából nem kész kód, hanem az elv ami érdekelne.
- 1140 megtekintés
Hozzászólások
iskolapélda szvsz.
ciklus{
m=read(n);
if(m!=n) utolsó futás
}
Az eredményt meg hozzáfűzheted egy mindig realloc-olt char tömbhöz.
- A hozzászóláshoz be kell jelentkezni
De ha van egy hatar, amig elmehet az adat merete, akkor szvsz nem erdemes realloc-olni (kiveve, ha a hatar gigabajtos magassagokban van, es a keresek 0,000001%-a igenyli ezt).
En ugy csinalnam, hogy megneznem, mi az atlagos adatmeret, ennel valamivel nagyobbra inicializalnam a puffert, es csak vegszukseg eseten realloc-olnek. Az ugyanis nem atomi muvelet, raadasul hibaforras is lehet (mit csinalsz, ha elfogyott a memoria?).
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
ja, az ok, de mit csinálok, ha pl nem érkezik > hanem negint < jön
tehát olvassam bytonként, az adatokat, és úgy töltsek fel egy buffert
mert valaki azt is tanácsolta, hogy olvassam block-okban, mert úgy sokkal gyorsabb lesz
a feladat egyszerűsége, nem jelenti azt, hogy a megoldás is egyszerű
ezért gondoltam, hogy megkérdezem, ki hogy oldaná meg
a teljes méret igazából behatárolható, mérések alapján, de nem lehet támaszkodni rá
- A hozzászóláshoz be kell jelentkezni
"valaki azt is tanácsolta, hogy olvassam block-okban, mert úgy sokkal gyorsabb lesz"
Ezt írtam én is. A block mérete n byte, n pontos értéke a behatárolt méret alapján meghatározandó.
- A hozzászóláshoz be kell jelentkezni
C++ esetén használj vector -t, aztán push_back() -kel tedd bele az újonan olvasott adatokat.
Létrehozás után a reserve() -vel foglalj elengedő helyet az elemeknek, hogy nem méreteződjön át minden push_back -nél.
- A hozzászóláshoz be kell jelentkezni
A problema ugyanaz mint itt, illetve itt is hivatkozunk ugye erre :) Szoval a lenyeg, hogy az alapproblema tokugyanaz mint a soronkenti beolvasas. Csak nem a sorvege karakterekre kell rakeresned a memoriaban levo darabok kozott, hanem erzekelni, hogy mikor van vege a fenti formaban bejovo rekordoknak. Ill. ha ugy tunik hogy vege van, akkor csekkolni hogy a rekord tartalma helyes-e, vagyis erre az ``hibát is észre kéne venni, ha van benne.'' reszre gondolok, barmit is jelentsen a hiba :]
A.
- A hozzászóláshoz be kell jelentkezni
ezeket, mindjárt megnézem, de pont hasonlóra gondoltam
- A hozzászóláshoz be kell jelentkezni
Egyik megközelítés: ciklusban olvasol a socket-ből, és a buffer-ben magad vadászol az adatokra, nyilvántartasz különféle állapotokat, kézzel hajtod az automatát. A memóriafoglalásra használhatsz realloc()-ot, de akár azt is csinálhatod, hogy mindig egy (pl.) 64K-s blokkot foglalsz le előre, abba olvasol, ha betelik, láncolod és újat foglalsz, majd a "végén" összemásolod egyetlen (akkorra már ismert méretű) blokkba a láncot, miközben mindjárt fel is szabadítod a láncszemeket (*). Ennek a megközelítésnek a jellemzője, hogy nagyon nehéz átlátni, és ha változik a protokollod, akkor megbolondulsz.
A másik megközelítés, hogy megírod a nyelvtant, majd valamilyen generátorral készítesz belőle egy parser-t (elemzőt). A kunszt itt az, hogy ne a parser-nél legyen a vezérlés, vagyis ne a parser-ben lévő ciklus hívogasson (akár callback-en keresztül, közvetve) read()-et, hiszen te egyszerre több socket-re is várhatsz éppen, pl. select()-tel. Így az az igény, hogy amelyik socket-en jön éppen adat, annak a parser-ét akarod hajtani; annyi byte-ot akarsz belenyomni, amennyi érkezett, és a redukciókhoz rendelt műveleteket callback-ként óhajtod végrehajtani. Na, ilyen eszköz
- újabban a GNU bison, ha jól tudom (
%pure-parser
,
info bison
),
- a Ragel és a Lemon (az első a lexer, a második a parser): itt van az a cikk, amire szükséged van!,
- végül nem bírom nem megemlíteni, hogy én is írtam egy ilyet (edp - externally driven parser); mindenesetre nem ajánlom :)
Persze ha nem gáz többszálúvá tenni a programot, akkor mindegyik "saját-vezérlésű" parser futhat a saját thread-jében, párhuzamosan kiadva a read()-eket, de ekkor majd a szinkronizálástól, kommunikációtól kapsz hülyét.
Egy parser generátor használatának nagy előnye, hogy (1) sokkal könnyebb a protokollon módosítani, (2) ha a nyelvtant nem rontottad el, akkor a parser is jó lesz, (3) nem kell kézzel vacakolnod az automatákkal (ezt mondjuk hülyeség előnyként megemlítenem; a parser generátornak ez nem előnye, hanem célja).
(*) A realloc()-nak, ha minden híváskor újra kell másolnia az előző blokkot, négyzetes műveleti igénye van akkor, ha a blokk méretét mindig egy konstanssal növeled; számtani sorozat összegképletében n^2-es tag van. Ha azonban az előző blokk méretét duplázod, akkor
2^0 + 2^1 + 2^2 + ... + 2^(k-1) = 2^k - 1 = n, vagyis ekkor ugyan potenciálisan dupla annyi memóriát fogsz lefoglalni, mint szükséged volna rá, ugyanakkor lineáris lesz a másolásigény.
Ha a láncolós módszert alkalmazod, akkor is lineáris a másolásigény (a végén 1 teljes menet).
- A hozzászóláshoz be kell jelentkezni
nagyon köszönöm, ezt a bő, szinte minden részletre kitérő választ
a linkeket átolvasom, okosodom belőlük
- A hozzászóláshoz be kell jelentkezni