Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Kako elegantno resiti blokiranje kod prostog chat klijenta (preko soketa)?

[es] :: C/C++ programiranje :: Kako elegantno resiti blokiranje kod prostog chat klijenta (preko soketa)?

[ Pregleda: 3774 | Odgovora: 8 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

vilyu
Web Developer
Beograd, Srbija

Član broj: 1188
Poruke: 444



+2 Profil

icon Kako elegantno resiti blokiranje kod prostog chat klijenta (preko soketa)?26.05.2005. u 02:04 - pre 230 meseci
Zdravo,

Jasno mi je da se kod servera koristi naredba select, ili fcntl kako bi se izbeglo blokiranje u naredbama accept i recv. Interesuje me koji je dobar metod da se recimo kod chat klijenta to isto izvede. Dakle, chat klijent treba da prima tekst sa servera, dok god ne ustanovi da je korisnik odlucio da posalje recenicu. Da li i ovde da primenim naredbu select i da onda proveravam: da li je stigla poruka od servera, da li korisnik salje recenicu, da li se nesto drugo dogodilo, pa iznova? Ako se telnetujem na prosti chat server koji svim prikacenim socket-ima prosledjuje pristigli tekst, telnet i prikaze tekst i posalje ono sto sam ja kucao. Kako to radi? Hvala unapred.
Pera električar 0637129710, BG, preporučujem.
 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1249



+96 Profil

icon Re: Kako elegantno resiti blokiranje kod prostog chat klijenta (preko soketa)?26.05.2005. u 09:10 - pre 230 meseci
select je majka! Nemoj da radis nista bez njega, svejedno je li klijent

ili server.
 
Odgovor na temu

vilyu
Web Developer
Beograd, Srbija

Član broj: 1188
Poruke: 444



+2 Profil

icon Re: Kako elegantno resiti blokiranje kod prostog chat klijenta (preko soketa)?27.05.2005. u 17:01 - pre 230 meseci
OK. A kako se sve to resava kada je u pitanju program sa FLTK (ili nekim drugim, nebitno) GUI-jem. Programiranje sa prozorima je, koliko shvatam, event based. Znaci, delovi programa se izvrsavaju kad se dogodi neki event. U network programiranju ja moram da imam neku petlju koja non stop proverava da li je nesto stiglo na socket. Da li onda da razdvajam socket klasu u nezavisnu nit, ili da to resim na neki drugi nacin. Vezbe radi je to sada chat klijent, interesuje me kako bih to dobro/elegantno resio i u bilo kom drugom slicnom programu. Hvala na vasem vremenu.
Pera električar 0637129710, BG, preporučujem.
 
Odgovor na temu

X Files
Vladimir Stefanovic
Pozarevac

SuperModerator
Član broj: 15100
Poruke: 4902
*.nat-pool.po.sbb.co.yu.

Jabber: xfiles@elitesecurity.org


+638 Profil

icon Re: Kako elegantno resiti blokiranje kod prostog chat klijenta (preko soketa)?27.05.2005. u 19:58 - pre 230 meseci
Citat:

OK. A kako se sve to resava kada je u pitanju program sa FLTK (ili nekim drugim,
nebitno) GUI-jem.

Nisam se javljao do sada, jer svo moje (sa)znanje vezano za socket-e je vezano
isključivo za VCL/C++Builder i komponente TClientSocket i TServerSocket (da ne
pominjem Indy ovog puta) koje su poprilično dobro koncipirane za problematiku
socket-a. Inače do sada sam projektovao/razvio desetak servera (servisna
aplikacija+socket-i) i to su za sada moje najkorisnije aplikacije, iako imam puno
složenijih projekata.

Dakle, sve ovo što kažem viđenje je iz ugla C++Builder-a i klasa TClientSocket i
TServerSocket.

Citat:

Programiranje sa prozorima je, koliko shvatam, event based. Znaci, delovi programa
se izvrsavaju kad se dogodi neki event.

Tačno, i to se odnosi i na socket-e.

Citat:

U network programiranju ja moram da imam neku petlju koja non stop proverava
da li je nesto stiglo na socket.

Ne. Kod ovih klasa čeka se event OnRead() i kod servera i kod klijenta, ili
OnGetThread() što je ono što mislim da bi tebe zanimalo! Drugim recima
sve je event based dok ne dodje do citanja, a onda mora thread i to samo u "modu"
za "uporedno" čitanje. Ima i neki drugi mod!

Citat:

Da li onda da razdvajam socket klasu u nezavisnu nit, ili da to resim na neki
drugi nacin.

Da, ali ako koristiš gore pomenute klase, novi thread ćeš otvarati samo radi
čitanja u "modu" koji predviđa uporedno čitanje.

Citat:

Vezbe radi je to sada chat klijent [...]

Koliko ja znam chat je i klijent i server, je li tako? Barem u najprostijem obliku,
kada su sve IP adrese poznate (stalne).

Evo ovako:

KLIJENT:
TClientSocket ima dva radna režima: ctBlocking i ctNonBlocking. Kod ovog prvog, kada
otvaras vezu sa serverom, recimo ClientSocket1->Open(), dok se ne pronadje server
ceo program je "blokiran". Ceknaje na server zavisi od nekih unapred u sistemu podesenih
mera, tako da cekanje u LAN-u traje 5 sekundi, dok cekanje na Internet-u traje mnogo
duze, mislim 30 sekundi. Kako program razlikuje LAN od Interneta, pojma nemam...

U ovom modu nema teorije da nekako prekines (limitiras) vreme cekanja sa event baziranim
nacinima, npr TTimer komponentom ciji bi event trebao da se "okine" na podeseno vreme,
recimo ClintSocket1->Close(). Jedini nacin je nekim zasebnim thread-om za prekidanje.

Ali tako se retko kada radi. Mnogo cesce se u smislu klijenata koristi onaj drugi,
ctNonBlocking mode, gde jednostavno pokusas otvaranje, a program "trci" dalje,
pa ako dodje do neke greske, javlja se event OnError(). Takodje try/catch je
*obavezan* jer program moze da se zbuni.

Evo kako se tada otvara konekcija:

Code:

// SOCKET_WAIT_FOR_CONNECTION je broj milisekundi kada odustajes od potrage...
try            
{            
   // **********************************************************************            
   SmsClientSocket->Active = false;            
   SmsClientSocket->Address = CONFIG_SMS_IP;            
   SmsClientSocket->Port    = CONFIG_SMS_PORT;            
   // **********************************************************************            
   SmsClientSocket->Active = true;            
   // **********************************************************************            
   int ms_start = GetTickCount();            
   while ( GetTickCount() - ms_start < SOCKET_WAIT_FOR_CONNECTION )            
   {            
      Forms::Application->ProcessMessages();            
      if ( SmsClientSocket->Active )            
         break;            
   }            
   if ( !SmsClientSocket->Active )            
   {            
      SmsClientSocket->Active = false; // <-- IZGLEDA TOTALNO GLUPAVO ALI NIJE!
      LogMessage( "sursrv.exe : SendToRecipients() > Sms > Timeout" );            
      GoSendMessageToLog ( SERVICE_SMS_SENDING_SOCKET_TIMEOUT_ERROR );            
   }            
   else            
   {            
      bool R = GoSendData ( SmsClientSocket, SmsMemStream, SOCKET_BUFFER_PORTION );            

      int ms_start = GetTickCount();            
      while ( GetTickCount() - ms_start < SOCKET_PROCESSMESSAGES )            
         Forms::Application->ProcessMessages();            

      if ( !R )            
      {            
         LogMessage( "sursrv.exe : SendToRecipients() > Sms > GoSendData()" );            
         GoSendMessageToLog ( SERVICE_SMS_SENDING_SOCKET_ERROR );            
         SystemOk = false;
         // ...
      }            
      else            
      {
         // ...
      }            
   }            
   // **********************************************************************            
}            
catch ( const Exception &e )            
{            
   LogMessage( "sursrv.exe : SendToRecipients() > Sms > Exception" );            
   GoSendMessageToLog ( SERVICE_SMS_SENDING_SOCKET_ERROR );            
   //SystemOk = false;            
}            


Ovo je otprilike kako resavam konektovanje + slanje: GoSendData(). Ova poslednja
funkcija je moja (nije clanica neke klase).

E sad, sledi drugi deo price:

SERVERI:
Serveri takodje mogu da imaju dva radna rezima: stNonBlocking i stThreadBlocking.
Server ne polazi ni od kakve pretpostavke i kakvom je rezimu bio klijent i
obrnuto. Da ne duzim, logicno je da server uporedo obradjuje vise zahteva i tada
se koristi event mod stThreadBlocking i OnGetThread() event. U njemu otvaras
thread, gde vrsis citanje i eventualno "odgovaranje" klijentu.

Ako te ovo i dalje zanima (kod i ostalo), javi pa da nastavim...
 
Odgovor na temu

vilyu
Web Developer
Beograd, Srbija

Član broj: 1188
Poruke: 444
Via: [es] mailing liste



+2 Profil

icon Re: Kako elegantno resiti blokiranje kod prostog chat klijenta (preko soketa)?27.05.2005. u 20:33 - pre 230 meseci
Citat:
Ne. Kod ovih klasa čeka se event OnRead() i kod servera i kod
klijenta, ili *OnGetThread()* što je ono što mislim da bi tebe
zanimalo!


Cekaj, nesto mora da okine taj event. Koliko zakljucujem iz tvog
odgovora, Socket klasa stavlja u nezavisan thread proveravanje da li je
nesto stiglo na socket, kako bi ostatak programa mogao paralelno da se
izvrsava. Proveravanje da li je nesto stiglo verovatno stoji u while(1)
petlji. Onda, u momentu kada neceg bude za citanje, klasa pusti OnRead
event i onda ti na neki nacin pristupas pristiglim podacima. Znaci,
neophodno je da i program na klijentu bude odradjen sa vise niti, da bi
cekanje na nove podatke moglo da se uskladi sa event based GUI-jem. Da
li sam dobro razumeo?

Mozda sam morao ranije da napomenem, ali vezbe radi pravim i sopstvenu
socket klasu, od nule. Tako da me zaista interesuje kako sve to
kvalitetno implementirati kako bi se kasnije lako koristilo.

Hvala
Pera električar 0637129710, BG, preporučujem.
 
Odgovor na temu

yooyo

Član broj: 4891
Poruke: 1101
*.beotel.net.



Profil

icon Re: Kako elegantno resiti blokiranje kod prostog chat klijenta (preko soketa)?27.05.2005. u 20:56 - pre 230 meseci
Kod server socket programiranja postoji generanlo 2 nacina: 1 thread po klijentu ili threadpool za sve klijente.

Prvi slucaj se koristi ako znas da nece biti puno korisnika na serveru pa mozes da priustis takav luksuz. U tom slucaj jeda thread cuci i prihvata konekcije. Kada se konekcija uspostavi on kreira klijent objekat i podize 1 thread za dalju komunikaciju.

Drugi slucaj (threadpool) se korisi u situacijama gde imas mnogo korisnika u istom trenutku. U tom slucaju postoji threadpool koji ceka na zadatke. Jednostavno... napravis zadatak "cekaj na konekciju" i gurnes ga u red na obradu. Jedan od threadova iz pool-a ce preuzeti taj zadatak i ako pristigne neka konekcija onda je prihvata i ponovo je stavlja u red na dalju obrau a taj thread je slobodan za nesto drugo. Princip je da neki thread prihvati zadatak i kad ga zavrsi svoj rezultat ili posalje na client socket ili ga stavi u red na dalju obradu. Broj threadova se moze regulisati i zavisi od broja procesora na serveru.

Pod windowsima mozes da pogledas IOCP (IO completion ports) koji nude generalno resenje za ovakve probleme.

Sto je klijenta tice, tu je stvar jednostavnija. Napravi 1 (comm) thread koji vrsi celu komunikaciju sa serverom, a UI (user interface) thread ostavi da radi svoj posao kao i pre. Kada nesto stigne sa mreze comm thread dekoduje poruku i salje event UI threadu.
Namesti da socket bude nonblocking tako da comm thread moze da prihvata evente od UI threada (kada korisnik zeli da posalje paketic).


yooyo
 
Odgovor na temu

X Files
Vladimir Stefanovic
Pozarevac

SuperModerator
Član broj: 15100
Poruke: 4902
*.nat-pool.po.sbb.co.yu.

Jabber: xfiles@elitesecurity.org


+638 Profil

icon Re: Kako elegantno resiti blokiranje kod prostog chat klijenta (preko soketa)?27.05.2005. u 21:03 - pre 230 meseci
Jesi li potrazio malo po netu, npr:

http://www.hal-pc.org/~johnnie2/winsock.html

... ima poprilicno dobar tutorijal. Mislim da bi ti koristio.
 
Odgovor na temu

vilyu
Web Developer
Beograd, Srbija

Član broj: 1188
Poruke: 444
Via: [es] mailing liste



+2 Profil

icon Re: Kako elegantno resiti blokiranje kod prostog chat klijenta (preko soketa)?28.05.2005. u 15:11 - pre 230 meseci
Citat:
Kada nesto stigne sa mreze comm thread dekoduje poruku i salje
event UI threadu.

OK, model mi je jasan. Samo ne znam kako da definisem novi event i kako
da ga posaljem. Trazio sam sad po FLTK dokumentaciji i naisao na
predefinisan set event-ova, ali nigde i na funkciju kojom bih definisao
neki svoj event. Mozete li mi pomoci oko toga?
Pera električar 0637129710, BG, preporučujem.
 
Odgovor na temu

leka
Dejan Lekić
senior software engineer, 3Developers
Ltd.
London, UK

Član broj: 234
Poruke: 2534
..31.216.81.gus.vf.siwnet.net.

Sajt: dejan.lekic.org


+2 Profil

icon Re: Kako elegantno resiti blokiranje kod prostog chat klijenta (preko soketa)?31.05.2005. u 18:20 - pre 229 meseci
FLTK NIJE generalni framework (za sve) - u pitanju je SAMO I JEDINO GUI ToolKit. Poslove oko Socket-a (u ovom slucaju) obavljaju druge (tudje) biblioteke. Moj predlog je, ako vec zelis da koristis obradu dogadjaja da koristis "C++ Sockets Library". URL: http://www.alhem.net/Sockets/ .
Ovde nema nikakvog govora o GUI-ju. Malo je preopsirna tema kako napisati chat klijent, ali u principu svaki chat klijent, pogotovo IRC klijent, treba da ima svoj sopstveni engine u kome se obradjuju pristigle poruke, kao i one koje treba da se posalju.
Za pocetak ce ti garant neke osnovne ideje dati dokumenti koji se nalaze ovde: http://tomasoft.sourceforge.net/ .
Dejan Lekic
software engineer, MySQL/PgSQL DBA, sysadmin
 
Odgovor na temu

[es] :: C/C++ programiranje :: Kako elegantno resiti blokiranje kod prostog chat klijenta (preko soketa)?

[ Pregleda: 3774 | Odgovora: 8 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.