Toon posts:

[WinSock/C] Non-blocking disconnect naar blocking omzetten *

Pagina: 1
Acties:

Verwijderd

Topicstarter
Beste mensen, ik ben bezig met een winsock programmatje en ondervindt een probleem met het zogenaamde 'blocking-' en 'non-blocking' mode.

Ik laat mijn programma namelijk weten doormiddel van message-mappen wanneer er een zogenaamde 'winsock event' gebeurd...

Dus wanneer windows een FD_CLOSE message stuurt, weet ik dat de verbinding tussen de server en de client verbroken is... De socket is dan niet meer geldig...

Vervolgens wil ik de socket opnieuw laten wachten op een inkomende verbinding,
maar het probleem is dat WSAAsyncSelect() de socket op non-blockingmode heeft gezet.
Dus ik kan niet zomaar een accept() functie erin gooien en wachten totdat de client weer een verbinding probeert aan te gaan: de functie zal de macro WSAWOULDBLOCK retourneren.

Dus ik maar op de MSDN zoeken hoe ik een socket die met de functie WSAAsyncSelect is aangeroepen terug kan zetten naar blocking-mode...
MSDN zegt me dat ik dan het volgende moet doen:


WSAAsyncSelect (hRemoteSocket,hwnd,1111,0); ioctlsocket(hRemoteSocket,FIONBIO,NULL);

Dat wil zeggen: WSAAsyncselect() nogmaals aanroepen op de socket en dit keer met een 0 als event parameter, en vervolgens ioctlsocket() aanroepen op de socket.

Resultaat bij mij: De socket blijft op non-blocking mode staan.... hij moet dus naar blocking mode.
Wie o wie kan mij helpen? Want dit is voor de meeste geen simpele vraag.

:/

Verwijderd

Verwijderd schreef op 26 juni 2004 @ 17:33:
WSAAsyncSelect (hRemoteSocket,hwnd,1111,0); ioctlsocket(hRemoteSocket,FIONBIO,NULL);

Dat wil zeggen: WSAAsyncselect() nogmaals aanroepen op de socket en dit keer met een 0 als event parameter, en vervolgens ioctlsocket() aanroepen op de socket.

Resultaat bij mij: De socket blijft op non-blocking mode staan.... hij moet dus naar blocking mode.
Wie o wie kan mij helpen? Want dit is voor de meeste geen simpele vraag.

:/
Volgens msdn moet het derde argument een pointer naar een long met waarde 0 of 1 zijn, dus probeer eens:

u_long arg = 0;
...
ioctlsocket(hRemoteSocket,FIONBIO,&arg);

Verwijderd

Topicstarter
Goed geprobeerd... Maar tevergeefs, ik heb het met een variabele geprobeerd...
De paramter is trouwens gewoon een long (int) , geen pointer.

:|

Verwijderd

Verwijderd schreef op 26 juni 2004 @ 19:02:
Goed geprobeerd... Maar tevergeefs, ik heb het met een variabele geprobeerd...
De paramter is trouwens gewoon een long (int) , geen pointer.

:|
Hier staat toch echt een pointer: http://msdn.microsoft.com...winsock/ioctlsocket_2.asp

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Je hebt toch een apart socket voor de server (listening socket) en de eigenlijke verbinding (return value van accept)? Kun je niet gewoon de eerste in blocking mode laten en alleen de tweede in non-blocking zetten?

www.madwizard.org


Verwijderd

Topicstarter
Ja maar die 2e moet juist in blocking-mode...
Ik begin trouwens mezelf steeds meer af te vragen of het wel met blocking mode te maken heeft.
De accept functie wordt namelijk de 2e keer met dezelfde sockets gewoon overgeslagen... Er is dan inderdaad een returnwaarde van INVALID_SOCKET en als ik met GetLastSocketError(zoiets heette het toch?) de fout probeer te achterhalen... is deze niet een van de volgende:

WSANOTINITIALISED
WSAENETDOWN
WSAEFAULT
WSAEINTR
WSAEINPROGRESS
WSAEINVAL
WSAEMFILE
WSAENOBUFS
WSAENOTSOCK
WSAEOPNOTSUPP
WSAEWOULDBLOCK

Sorrie, het is ook een beetje een ingewikkelde code (die ik niet openbaar stel)
dus misschien heb ik mij laten misleiden door mijn eerste ingeving dat accept() niet op blockingmode wil aangezien die functie overgeslagen wordt... Maar het schijnt geen van deze errors hierboven te zijn.

Ik ben radeloos. ;(

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

Verwijderd schreef op 26 juni 2004 @ 20:28:
Ja maar die 2e moet juist in blocking-mode...
Ik begin trouwens mezelf steeds meer af te vragen of het wel met blocking mode te maken heeft.
De accept functie wordt namelijk de 2e keer met dezelfde sockets gewoon overgeslagen... Er is dan inderdaad een returnwaarde van INVALID_SOCKET en als ik met GetLastSocketError(zoiets heette het toch?) de fout probeer te achterhalen... is deze niet een van de volgende:
INVALID_SOCKET is gewoon een indicatie dat de betreffende handle geen socket is. Het kan dat de betreffende handle gewoon gesloten is, of dat er om een of andere reden er een ongeldige handle wordt doorgegeven. Da's echter debugwerk, en zonder code ook wat lastig te zeggen.

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Je roept accept toch niet op het tweede socket aan? Het serversocket gebruik je alleen maar voor accept en verder nergens voor. Het clientsocket (return value van accept) gebruik je alleen voor de verbinding. Is die gesloten dan is het afgelopen en moet je het socket opruimen (closesocket). Sockets hergebruiken werkt meestal niet of niet goed (heeft bepaalde eisen geloof ik) en zowieso wil je dat volgens mij ook niet. Een nieuwe verbinding zal nooit op het clientsocket binnenkomen, alleen maar op het serversocket.

www.madwizard.org


Verwijderd

Topicstarter
Dan maar een beetje C++ en er een pointertje van maken met new SOCKET...
Ik zal het morgen eens proberen het is wat laat nu, erg bedankt alvast voor de reacties.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Titel begrijpelijk opgefixt, zodra ik nuchter ben kijk ik er nog wel eens inhoudelijk naar ;)

Professionele website nodig?


Verwijderd

Topicstarter
Ik denk dat ik dan toch maar wat code moet vrijgeven, ach het kan ook geen kwaad:
Dus ná een bericht te hebben ontvangen: FD_CLOSE doe ik het volgende, om mijn socket terug in blockingmode te krijgen en te wachten op een verbinding die we kunnen accepteren:

closesocket(hRemoteSocket);
closesocket(hSocket2);

Terug naar blocking-mode!
unsigned long int arg = 0;

WSAAsyncSelect (hRemoteSocket,hwnd,1111,arg);
WSAAsyncSelect (hSocket2,hwnd,2222,arg);

ioctlsocket(hSocket2,FIONBIO,NULL);
ioctlsocket(hRemoteSocket,FIONBIO,NULL);

hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(5016); //poort instellen.
sockAddr.sin_addr.S_un.S_addr = INADDR_ANY;
bind(hSocket, (sockaddr*)(&sockAddr), sizeof(sockAddr));
listen(hSocket, SOMAXCONN);
iRemoteAddrLen = sizeof(remoteAddr);
hRemoteSocket = accept(hSocket, (sockaddr*)&remoteAddr, &iRemoteAddrLen) ;


Ik hoop dat nu iemand het weet. :*)

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Closesocket sluit niet de verbinding, maar de socket descriptor (de handle zelf zeg maar). Je kunt daarna dus geen functies meer aanroepen op deze handles, vandaar dat je waarschijnlijk INVALID_SOCKET krijgt. Maar dan nog snap ik je code niet helemaal. Heb je nou 3 sockets (hSocket, hSocket2, hRemoteSocket)? Waar is hSocket2 dan voor?

www.madwizard.org


Verwijderd

Topicstarter
Het is een programma dat meerdere verbindingen met een vast aantal verschillende clients maakt en servers, de hele code is ook zeer groot.
Heb je een oplossing hoe ik dit wel goed zou kunnen doen? (Ja we zijn er bijna uit :))
Groet Robert.

Verwijderd

Ff een vraagje: waarom wil je je listening socket blocking hebben, maar je client sockets non-blocking?

Het lijkt mij voor de hand liggend om of alles non-blocking te laten, of alles om te zetten in blocking en threads, anders kom je waarschijnlijk nog meer in de problemen. Als je b.v. single-threaded werkt en er zijn nog clients verbonden dan kun je geen blocking accept op die listening socket doen (anders blockt je process en kun je je clients niet bedienen).

Over je concrete probleem:

Ik ben geen winsock expert, maar normalerwijze kun je niet onmiddelijk een socket aan een poort/interface binden nadat je die poort vrijgeeft (door de socket te closen), er wordt dan door de tcp/ip-stack nog in de achtergrond "gelingerd" om halve connecties e.d. naar de poort af te breken (anders zou het nieuwe serverprocess dus connecties van een vorig process kunnen accepten hetgeen een veiligheidsrisico kan zijn). Je kunt dat voorkomen door een socketoption te zetten voor de call naar bind; onder posix is dit de SO_REUSEADDR optie, ik weet niet precies hoe dit onder windows werkt.

Verder is het handig de return-codes van de socketfuncties zoals bind, listen en ioctlsocket af te handelen zodat je weet wat er precies fout gaat.

Verwijderd

Topicstarter
Bedankt mietje(ja klinkt zo lullig), en natuurlijk de rest.
Je moet inderdaad die sockets niet closen, maar gewoon opnieuw accept() functie aanroepen en de sockets ongedeert laten...
Wat een vaag topic was dit... Ben blij dat het voorbij is... nogmaals bedankt iedereen. _/-\o_
Pagina: 1