2015-05-26 20:26 GMT+03:00 Adrian Stanciu <[email protected]>: > 2015-05-26 19:17 GMT+03:00 Georgiana Diana <[email protected]>: >> Buna, >> Eu tot am niste nelamuriri legate de citirea asincrona / trimiterea cu send >> (inline): >> > > Bună, Georgiana! > >> 2015-05-25 20:53 GMT+03:00 Adrian Stanciu via so <[email protected]>: >>> >>> 2015-05-25 20:49 GMT+03:00 Madalina Hristache via so >>> <[email protected]>: >>> > Salut, >>> >>> Bună, Mădălina! >>> >>> > >>> > Am câteva nelămuriri și am nevoie de clarificarea lor ca să pot continua >>> > tema. >>> > >>> > 1. Când transmitem un fișier din directorul static, trimitem header-ul >>> > HTTP >>> > cu send (non-blocant, asincron), apoi fișierul cu sendfile. Fără nicio >>> > legătură cu libaio.h, da? >>> >>> Da, așa este. >>> >>> > >>> > 2. Când transmitem un fișier din directorul dynamic, îl citim de pe disc >>> > cu >>> > apeluri legate de libaio.h, apoi îl punem pe socket. Și cum îl trimitem? >>> > Cu >>> > send? Sendfile? La partea asta sunt în ceață. >>> > >>> >>> Cu send(). >> >> >> In exemplul din laborator [1], precum si in exemplul sugerat in tema [2] >> (xmailserver), am observat ca se face read pe un file descriptor, pentru a >> notifica serverul atunci cand operatia asincrona de citire s-a terminat. >> >> 1) Este acest read blocant, sau nu ? > > Acel read() pe eventfd este blocant, dar nu se va bloca dacă îl apelâm > atunci când primim o notificare de la kernel, prin intermediul epoll. > >> 2) Care ar trebui sa fie workflow-ul server-ului in cazul trimiterii unui >> fisier dinamic ? Ma gandeam ca unul posibil este acesta, dar inca nu imi dau >> seama daca este corect: >> >> initializare io_context (in main, inainte de logica serverului); > > Este mai ușor dacă folosești un context IO per conexiune. > >> in server, primirea unui request de citire fisier dinamic; >> trimiterea catre client a unui raspuns: 200/404, in functie de caz, prin >> send-uri repetate (metoda comuna, atat pentru fisier static, cat si pentru >> dinamic); >> dupa trimiterea header-ului, in cazul unui fisier dinamic, serverul seteaza >> un eventfd si submite un request de read pentru contextul aio -- actiune >> neblocanta; >> serverul face read pe eventfd-ul anterior -- actiune blocanta ?; > > Practic neblocantă dacă citirea se face la semnalizarea pe eventfd din > partea epoll. > >> in urma notificarii de terminare a citirii din fisier a unui buffer in >> general mai mic decat dimensiunea fisierului, serverul face apeluri send >> repetate, pentru a trimite buffer-ul proaspat citit; -- in timpul acesta, se >> presupune ca serverul initiaza o noua cerere de citire asincrona, sau >> asteapta trimiterea buffer-ului curent ? ; > > E mai ușor dacă nu faci aceste operații simultan; e mai eficient dar > ar trebui să tratezi în același timp mai multe tipuri de evenimente > (read din fișier, send pe socket), care ar fi starea conexiunii? iar > complexitatea implementării ar fi mai mare. > >> serverul continua sa citeasca bucati de fisier si sa le trimita catre >> client. >> >> 3) Este corect ca in functia de trimitere fisier, pentru cazul unui fisier >> dinamic, si care se tot apeleaza in bucla principala a server-ului (pentru >> ca epoll este setat pe out, cat timp trimit un fisier), sa verific si sa >> schimb starea conexiunilor (de ex, cat timp trimit fisierul, starea sa fie >> SENDING_DATA, apoi, cand citirea asincrona se termina, pur si simplu sa >> schimb starea in DATA_SENT si sa inchid conexiunea) ? > > Poți să: > * activezi EPOLLIN pe eventfd pentru a aștepta finalizarea citirii > asincrone a unei bucăți din fișier > * planifici citirea asincronă a unei bucăți din fișier > * activezi EPOLLOUT pe socket
Nu am spus complet aici ... activarea EPOLLOUT pe socket se face când citirea asincronă a fost încheiată. Atunci avem date de trimis. > * când ești notificată de epoll că poți să trimiți pe socket, trimiți > bucata de fișier > * dacă nu s-a trimis întreaga bucată mai aștepți un nou eveniment de > EPOLLOUT pe socket din partea epoll și apoi trimiți ce ți-a mai rămas > și tot așa > * când ai terminat de trimis acea bucată, dezactivezi EPOLLOUT pe > socket (căci deocamdată nu mai ai ce trimite) > * o iei de la capât pentru a citi următoarea bucată din fișier > * când ai trimis întreg fișierul se poate închide conexiunea > Adrian _______________________________________________ http://ocw.cs.pub.ro/courses/so/info/lista-discutii
