- Function ClientConnectionThread.execute;
- Begin
- // initializare
- Repeat
- ReceivedBytes := recv(ConnectionSocket,Buffer,SizeOf(Buffer),0);
- If (ReceivedBytes = 0)
- Then
- Begin
- OK := False;
- End;
- If (ReceivedBytes = SOCKET_ERROR)
- Then
- Begin
- If (WSAGetLastError <> WSAEWOULDBLOCK)
- Then
- Begin
- OK := False;
- End
- End;
- If (OK = True)
- Then
- Begin
- If (ReceivedBytes > 0)
- Then
- Begin
- if ((verificare daca packetul corespunde formatului stabilit -- ca sa nu permita aplicatiilor oarecare sa se conecteze/sa ia informatii etc) = false)
- then
- Begin
- ok := False;
- //deconectare
- End
- Else
- Begin
- //executa ce trebuie sa faca clientul
- End;
- End;
- End;
- Until ((OK = False) Or (Terminated));
- End;
Folosesc ca mijloc de transmisie al datelor WinSock2 prin TCP.
Ma intreb cum sa fac un server (asa cum sunt cele de la World of Warcraft -- un exemplu oarecare... pe care stiu ca multi il cunosc), care sa accepte si sa mentina foarte multe conexiuni deodata(poate chiar peste 100.000).
Clientul se conecteaza la server si trebuie sa mentina conexiunea activa. la client folosesc non-blocking.
Codul de la client(socket TCP blocking)
Serverul trebuie sa deschida un port, sa accepte conexiuni prin el, apoi sa le ia la rand in continuu si sa primeasca datele. (socket TCP NON-blocking)
- Function ServerConnectionThread.execute;
- Begin
- // initializare
- xx := 0;
- While (Not Terminated) Do
- Begin
- ReceivedBytes := recv(Conexiune[xx],Buffer,SizeOf(Buffer),0);
- if (nu s-a primit nici un mesaj in ultimele 16 secunde)
- Then
- Begin
- OK := False;
- End;
- If (ReceivedBytes = 0)
- Then
- Begin
- OK := False;
- End;
- If (ReceivedBytes = SOCKET_ERROR)
- Then
- Begin
- If (WSAGetLastError <> WSAEWOULDBLOCK)
- Then
- Begin
- OK := False;
- End
- End;
- If (OK = True)
- Then
- Begin
- If (ReceivedBytes > 0)
- Then
- Begin
- if ((verificare daca packetul corespunde formatului stabilit -- ca sa nu permita aplicatiilor oarecare sa se conecteze/sa ia informatii etc) = false)
- then
- Begin
- ok := False;
- End
- Else
- Begin
- //executa ce trebuie sa faca serverul
- End;
- End;
- End;
- if (ok = false)
- Then
- Begin
- deconectare;
- End;
- xx := (xx + 1) Mod NumarulConexiunlor;
- End;
- End;
Acum problema este urmatoarea : in loop-ul de la server in care se repeta apelarea lui recv, cpu este ocupat 100% si celelalte threaduri din program se executa foarte incet.(serverul e non-blocking deoarece in caz ca un client nu a trimis nimic, sa treaca sa verifice urmatoarea conexiune. clientul nu are decat o singura conexiune si de aceea am pus blocking). Daca recv nu a primit nici un mesaj de la client, returneaza -1 si WSAGetLastError() returneasa WSAWOULDBLOCK = nu e nici un mesaj primit, incearca mai incolo.
Exista o metoda de a crea partea de conectivitate a serverului astfel incat sa ocupe cat mai putina memorie si sa fie cat mai rapid (fara ca cpu sa fie 100% ocupat)? Am cautat si nu am gasit raspunsuri exacte. Unele solutii ziceau de folosirea functiei Select(), dar nu stiu cum sa o folosesc (nu inteleg nimic din documentatia functiei).
Nu doresc sa folosesc metoda "un thread pe conexiune" cu socket TCP Blocking deoarece am auzit ca limita e 2000 thread-uri pe sistem deoarece fiecare thread ocupa 1MB memorie, si pe 32 biti limita de memorie RAM pe care o poate folosi un program este de 2GB (vreau sa pot sa mentin mai mult de 5000 conexiuni in acelasi timp).
PS. Nu vreau un design gen Clientul trimite, serverul executa si apoi ii trimite rezultatele inapoi la client, ci clientul trimite date, serverul le foloseste, si trimite cand vrea anumite informatii catre toti sau o parte din cliente.
Welcome to BitCell. Click here to register !
.
Am zis sa astepti 20ms inainte de a citi