Egy kis erőforrásigényű webszervert készítek, az LWIP tcp kezelésére alapozva, de nem sikerül megtalálnom az optimális HTTP csomagküldési módszert.
Ha az LWIP netconn csomagjára bízom a teljes pufferkezelést, akkor viszonylag gyakran előáll a termelő-fogyasztó probléma, emiatt befagy a kérelem kiszolgálása.
Emiatt az LWIP raw csomagját használom, ami szép gyorsan képes kiszolgálni a kérelmeket, de sehol semmilyen dokumentációt nem találok arról, hogy hogyan kellene generálnom egy HTTP kérésre a választ.
A példák alapján:
- ha tcp-echo szerű válaszokat akarnék, azaz egy csomagra egy csomagot válaszul, akkor a kérelem TCP csomag fogadásának (tcp_recv) eseményénél rögtön el is küldhetem tcp_write művelettel a válasz csomagot.
- ha fix, nagyméretű pufferből akarnák választ kiszolgálni, akkor a beérkező csomag fogadásánál elküldök egy tcp_sndbuf() által meghatározott maximális méretű csomagot, majd a csomag fogadásának visszaigazolása után egy újabbat és egy újabbat ...
De mi van, ha dinamikusan akarok sok válaszcsomagot küldeni egyetlen beérkező tcp kérelemre?
Ha a tcp_recv eseményénél elkezdem tcp_write()-tal teleírni a puffert, a válasz soha nem jut el a kérelmezőhöz.
Olyan, mintha a tcp_recv esemény lefutása után kezdené csak el kiüríteni a tcp_write()-tal teleírt puffert. Azaz pici, rövid válaszokat könnyű itt generálni, de nagy hosszú válaszokatat nem. S bár van olyan művelet, amivel tudom jelezni, hogy a kérelem csomagja már feldolgozva, ezek után sem kezdődik meg rögtön a válasz elküldése.
Mivel a dokumentációk sehol sem említik ezt, azt várnám, hogy a tcp_write()-tal teleírom a puffert, ami a háttérben, azonnal elküldésre kerül, amint lehetőség nyílik rá. Tehát írok, majd várok, ha már nincs hely a tcp puffer-ban, és ha kiürült a puffer, folytatom tovább az írást.
Ez azonban rém lassú kommunikációt ereményez. Ha néha manuálisan beteszek egy tcp_output() műveletet, hogy küldje ki a puffert, ez gyorsít, de még mindig nem azonnali a válasz.
Nem tudom, hogyan kellene használnom a tcp_write parancsot hogy optimálisan tudja visszaküldeni a választ.
Jelenleg a legjobb megoldásom, hogy a kérelem fogadásánál elindítok egy külön szálat, ami elkezd tölteni egy puffert, és az eredeti szálban pedig figyelem, hogy van-e a pufferban adat, ha igen, akkor a tcp_write()-tal elküldöm, míg a puffer ki nem ürül, és lezárásra nem kerül. Ekkor én is lezárom a tcp kapcsolatot.
Az eredmény bár működik, de mégis nyökögős és siralmas.
A tcp_write már maga is kezel egy puffert, teljesen feleslegesnek tűnik párhuzamosan még egy kezelése. De nem tudom, mi lenne az optimális módja a csomagok küldésének. És akkor még a POST kérelmekről nem is beszéltem, ahol a POST adat egy külön csomagban érkezik, tehát nem elég az első fogadott csomagot ismernem ahhoz, hogy válaszoljak. Természetesnek tűnik, hogy akkor először fogadjunk minden csomagot, és ezek után kezdjünk csak el válaszolni, de ez meg túl erős megkötésnek tűnik, ha például egy fájlfeltöltést akarnánk kezelni, ahol POST-ban jön a feldolgozandó adat folyamatosan.
Tehát minden beérkező kérelem esetén kellene tudnom valamekkora választ generálnom, és ezt folyamatosan vissza kellene tudnom juttatni a kliens felé, függetlenül a válasz méretétől. Ha pedig megtelik a puffer, valahogy várakoztatnom a válasz generálását.
A feladatot csak nehezíti az, hogy nem túl sok erőforrás áll a webszerver rendelkezésére, így az nem megoldható, hogy először legenerálom a teljes választ egy pufferbe, majd onnan szépen egyesével kiküldöm a csomagokat, mivel a teljes válasz egyszerűen nem fér el a memóriában.
Ha valakinek van tapasztalata alacsony szintű webszerver készítésében, érdekelne, hogyan oldotta meg ezt a problémát.
De, ha tudtok egy jó leírást arról, hogy pontosan hogyan is kell zajlania a HTTP alatt a csomagok cseréjének, és ezt az LWIP hogyan támogatja, az is nagy segítség lenne.
És köszönöm, már azt is, ha csak eddig elolvastad. ;)