[ Wajda.W @ 13.11.2009. 23:00 ] @
Imam problem kod bind funkcije, funkcija mi uvek vrati gresku, tj nikad ne uradi bind uspesno, a ne znam zbog cega.
Ja sam ovako odradio:
Code:

sockaddr_in myAddr;
    WORD wVersionRequested;
    WSADATA wsaData;
    int err, listenSocket;

    wVersionRequested = MAKEWORD( 2, 2 );

///WSAStartup

err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0)
    {
        AddString(hwnd,"Error: Could not find usable WinSock DLL !");
        return;
    }


    if (LOBYTE(wsaData.wVersion ) != 2 || HIBYTE(wsaData.wVersion ) != 2 )
    {
        AddString(hwnd,"Error: Could not find usable WinSock DLL !");
        WSACleanup();
        return;
    }

if(listenSocket = socket(AF_INET,SOCK_STREAM,0) == INVALID_SOCKET)
{
// obrada greske...
}

char yes = '1';
    myAddr.sin_family = AF_INET;
    myAddr.sin_port = htons(PORT);          // short, network byte order
    myAddr.sin_addr.s_addr = INADDR_ANY;    // choose this computer IP address
    memset(&(myAddr.sin_zero), '\0', 8);    // rest of structure fill with zeroes

    if (setsockopt(listenSocket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == SOCKET_ERROR)
{
// obrada greske
}

if(bind(listenSocket, (struct sockaddr *)&myAddr, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
// obrada greske
}


E ovako, prvo sam probao bez ovo "setsockopt" i uvek mi je prijavljivalo gresku, ja sam greske obradio (samo ih ovde nisam napisao radi preglednosti) sa GetLastError() ali je kod greske 0 pa ne znam sta se desava, zatim sam sve to isto probao sa tim "setsockopt" misleci da je mozda adresa u upotrebi.
Kad sam stavio setsockopt on mi izbacuje gresku u setsockopt, ja sam i te greske takodje obredio sa GetLastError() ali i tu greska ima kod 0 pa ne znam sta se desava....

Da li neko mozda zna zasto socket ne moze da uspostavi bind?
[ Mihajlo Cvetanović @ 14.11.2009. 20:05 ] @
Umesto GetLastError probaj sa WSAGetLastError. Probaj da staviš nulu umesto vrednosti PORT. Ovde ima bližih objašnjenja:

http://www.sockets.com/winsock.htm#Bind

Cela stranica je korisna.
[ Wajda.W @ 14.11.2009. 20:28 ] @
Da, moja greska, koristio sam WSAGetLastError() samo sam pogresno napisao.
Ne mogu koristiti 0 jer mi treba za listen kako bih klijenti mogli da me nadju po IP adresi i portu pa zato moram da prosledim odredjenu vrednost.
[ Mihajlo Cvetanović @ 14.11.2009. 20:42 ] @
Možda je taj port već zauzet. Pogledaj sa "netstat -an", da li taj port postoji kao LISTENING. Druga stvar, možda ti Windows ne dozvoljava da otvoriš port koji je suviše "nisko" (broj manji od 1024), probaj da promeniš broj.
[ Wajda.W @ 15.11.2009. 13:31 ] @
Znam da ne moze da bude manji od 1024, stavio sam 2250.
Pozvao sam "netstat -an" i nije zauzet taj port...
Stvarno ne znam u cemu je problem, probacu sa poco bibliotekom kad nadjem malo vremena, nista drugo mi ne pada na pamet.
[ mmix @ 15.11.2009. 14:30 ] @
Naravno da moze da bude manji od 1024 pod uslovom da je slobodan, to je samo preporuka da ne koristis <1024 za javne servise jer su ti portovi rezervisani za IANA registrovane servise. Kad ne bi mogao da otvoris port 80 npr ne bi ti radio ni apache ni skype.
[ mmix @ 15.11.2009. 15:30 ] @
Malo si pozurio sa kodiranjem da optimizujes sors pa si se zbunio sa operatorima. == ima veci prioritet od =, pa se ovaj statement:

listenSocket = socket(AF_INET,SOCK_STREAM,0) == INVALID_SOCKET

svodi na listenSocket = (socket(AF_INET,SOCK_STREAM,0) == INVALID_SOCKET) sto je uvek false, pa ti je listenSocket uvek 0 i onda pukne posle na socket operacijama sa 10038 (socket operation on non-socket).

ubacu zagrade da odredis prioritet

if((listenSocket = socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET)
[ mmix @ 15.11.2009. 15:43 ] @
PS: Ne zaboravi da pozoves listen(listenSocket, SOMAXCONN) iza bind, pre toga nece poceti slusanje na portu niti ces videti svoju aplikaciju u netstat spisku.
[ Wajda.W @ 15.11.2009. 21:18 ] @
Ne mogu da verujem!!!!
Hvala ti mmix.
Nemas pojma koliko sam sad srecan!
Ne mogu da verujem da sam napravio takvu gresku, iskreno ne verujem da li bi mi ikada palo na pamet to...
U svakom slucaju radi kako treba i od sada tu gresku ne verujem da cu ponovo napraviti posto mi je oduzela 3 dana...
[ Wajda.W @ 19.11.2009. 20:28 ] @
E sada, jos jedan problem.
Tj. vise je pitanje sta da radim.
Ja imam posebnu nit za svakog klijenta koji se nakaci na moj server, e sada, posto je recv() f-ja blokira, ja ne mogu da signaliziram nit spolja sa nekim semaforom pa da se ona regularno zatvori, nego bih morao da napravim da budu non-blocking operacije ako zelim da ih sve lepo pozatvaram kad gasim server.
Da li da ih zatvaram sa terminate(), cuo sam da je to losa metoda, da bi trebalo da se niti zavrse regularno, ili da pravim neblokirajuce operacije pa da ih zatvorim nekim signalom?
I ako je odgovor da je bolje da budu non-blocking onda kako da u winsock-u namestim da socket bude non-blocking?
[ Mihajlo Cvetanović @ 20.11.2009. 08:00 ] @
Bolje je da budu neblokirajuće. U Linuxu se koristi valjda fcntl ili ioctl, proguglaj malo. U Windowsu je za server bolje da se koristi I/O completion port, što je malo komplikovanije programiranje, ali je efikasnije za Windows.
[ deerbeer @ 20.11.2009. 08:30 ] @
Citat:

I ako je odgovor da je bolje da budu non-blocking onda kako da u winsock-u namestim da socket bude non-blocking?

Probaj sa winsock2 funkcijama :
http://msdn.microsoft.com/en-us/library/ms741688%28VS.85%29.aspx
[ deerbeer @ 20.11.2009. 14:15 ] @
Efikasno gasenje treda mozes isto tako uraditi i sa blokirajucom recv metodom,
pod uslovom da recv cita manje blokove podataka po 4K efikasnije je a i recv se nece blokirati na neko duze vreme
a samim tim ceo posao bi bio u nekoj petlji koju ti kontrolises
Npr. .
Code:
 
#define BUFFER_SIZE 4096 

int nBytesRead = 0 ; 
do 
{
  char szBuffer [BUFFER_SIZE]; //bufer 
  ZeroMemory(szBuffer,BUFFER_SIZE) ; 
  szBuffer[BUFFER_SIZE]= '\0' ; 

  // ako van ovog threda pozoves SetEvent(hStopServer) izlazis iz petlje .. 
  // u suprotnom ovaj wait  nece blokirati thread jer je setovan na 0 ms. 

   if (WaitForSingleObject(m_hStopServer,0) == WAIT_OBJECT_0) {
      break ; 
   }
   nBytesRead  = recv( m_Socket,szBuffer , BUFFER_SIZE, 0));

   if (nBytesRead == SOCKET_ERROR) //socket error 
     break ; 

  // uradi nesto sa podacima (szBuffer ) i smesti ih u neki veci bafer ili niz 

}
while (nBytesRead >0) ; 


Negde u kodu za gasenje threada
Code:


//setujes event za izlazak iz petlje za citanje .
SetEvent (m_hStopServer) ;  

//sacekas recimo 5 sec. da se  tread zavrsi 
WaitForSingleObject (m_hThread,5000)
[ Mihajlo Cvetanović @ 20.11.2009. 16:56 ] @
Neće to da radi, i nema veze sa veličinom input bafera. Ako koristiš i bafer od samo jednog bajta, a nema šta da se preuzme iz soketa, onda je recv zablokiran na neograničeno vreme.
[ Wajda.W @ 21.11.2009. 11:34 ] @
[/quote]
Citat:
Mihajlo Cvetanović: Neće to da radi, i nema veze sa veličinom input bafera. Ako koristiš i bafer od samo jednog bajta, a nema šta da se preuzme iz soketa, onda je recv zablokiran na neograničeno vreme. 

Nece bas zbog toga, mogu ja da namestim da klijent stalno salje bajt ili tako nesto da bi to radillo, ali mislim da to nije resenje, pa cu se pozabaviti sa sa neblokirajucim socketma kad budem imao vremena.
Ako ne uspem, onda ce da radi sa terminate iako to nije najbolji nacin...
Sutra cu se pozabaviti s tim pa vam javim kako sam odradio, danas sam u guzvi...
[ milanche @ 21.11.2009. 18:38 ] @
Postoji par dobrih resenja kojima se izbegava da thread bude blokiran cekajuci na podatke sa socket-a.

Prva metoda je potpuno portabilna na sve platforme, postoji jos od ranih dana Berkeley sockets, bazirana je na
select( ) funkciji (primenjiva kako na sockete, tako i na pipes). Prvo se sa funkcijom fd_set definise kolekcija
socket-a koja ce se posmatrati, a zatim se pozove select( ) da osmatra sta se desava sa definisanom kolekcijom.

Fora je sto select( ) ima opciju timeout-a, tako da thread mozes da napises u ovom fazonu:
(pseudo code):

petlja:
1) odreaguj na moguce komande thread-u (recimo: komanda za terminiranje) ako su pristigle
2) oformi kolekciju socket-a koju posmatras (pomocu fd_set), i pozovi select( ) definisuci vreme cekanja na neki kraci period
3) ako je select( ) izasao na bazi timeout-a, vrati se na pocetak petlje
3) ako je select( ) izasao zato sto je detektovao da ti je socket signalled sto u tvom slucaju znaci da je primio podatke,
onda ocitaj primljene podatke i prosledi ih gde treba
4) vrati se na pocetak petlje

Drugi pristup (ne znam kakva su ti ogranicenja u pogledu framework-a) je vezan za Windows koji pruza nekoliko nacina da
se se sa socket-ima radi asinhrono:
- WSAAsyncSelect( ) kojim mozes da specificiras windows message koji hoces da bude pozvan cim socket nesto primi
- WSAEventSelect( ), slicna stvar samo specificiras event objekat koji ce biti signalled
- callback funkcije (WSASend( ), WSASendTo( ), WSARecv( ), WSARecvFrom( )) koje socket zove cim se odgovarajuci dogadjaj desi
- gotove klase CAsyncSocket

Za ovaj drugi pristup postoje neka ogranicenja ako projekat pises za mesovito okruzenje tipa Windows desktop - Windows Mobile i slicno,
jer su samo neka resenja potpuno portabilna sa jednog na drugi flavor Windows-a.
[ Wajda.W @ 23.11.2009. 19:32 ] @
Uspeo sam preko select() da uradim....
To mi je delovalo kao najjednostavniji nacin.
Hvala svima na odgovorima!