Witam,
Pisze serwer odbierający dane UDP broadcast ( w BCB ) używając funkcji recvfrom().
Funkcja ta niestety jest blokująca, i "wiesza" mi program, a ja w międzyczasie muszę wykonywać w nim
inne operacje, więc muszę jakoś uniknąć blokowania.
Poczytałem artykuły i doszedłem do wniosku że pomoże mi funkcja select() lub/i ioctlsocket ( raczej
nie chciałbym używać wątków ).
Proszę o wskazówki w jaki sposób pozbyć się blokowania... Napisałem poniższy kod z użyciem
wspomnianego select i ioctlsocket, jednak nadal to nie to o co mi chodziło. Prawdopodobnie popełniłem
gdzieś wstrętną gafę ;-P
Nie wiem czy dobrze kombinowałem - chciałem za pomocą select() funkcją FD_ISSET wykrywać czy na
gnieździe s_socket są dane do odebrania, jeśli tak, to przełączam gniazdo w stan blokowania ( i
odbierania ), a jeśli nie ma danych do odebrania to w stan nieblokujący...
Niedziałający poprawnie fragment kodu odpowiedzialny za odbieranie UDP z użyciem select ( wszystko w Timerze ):
//------------------------------------------------------------------------
// Utworzenie gniazda
//------------------------------------------------------------------------
if (WSAStartup( MAKEWORD( 2 , 0 ) , &WSD) != 0) {
Label1->Caption="Nie udało się wczytac biblioteki WinSock...!";
}
s_socket=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
char broadcast = '1';
if(setsockopt(s_socket,SOL_SOCKET,1,&broadcast,sizeof(broadcast)) < 0)
{
Label1->Caption="Błąd podczas ustawiania opcji broadcastu...";
closesocket(s_socket);
}
//------------------------------------------------------------------------
// ODEBRANIE datagramu
//------------------------------------------------------------------------
SenderAddr.sin_family=AF_INET;
SenderAddr.sin_port=htons(67);
SenderAddr.sin_addr.s_addr=INADDR_ANY;
if (bind(s_socket,(sockaddr*)&SenderAddr, sizeof (SenderAddr)) < 0)
{
Label1->Caption="Nie udało się wykonac bind dla socketu...";
closesocket(s_socket);
}
fd_set read, write, excp; // SELECT()
int max = s_socket;
FD_ZERO(&read);
FD_SET(s_socket, &read);
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
if(select(max + 1, &read, NULL, NULL, &timeout))
{
if(FD_ISSET(s_socket, &read))
{
unsigned long flags=0;
ioctlsocket(s_socket, FIONBIO, &flags);
recvfrom(s_socket,RecvBuf,BufLen,0,(SOCKADDR *)&SenderAddr,&SenderAddrLen);
}
else
{
unsigned long flags=1;
ioctlsocket(s_socket, FIONBIO, &flags);
}
} else Label1->Caption="Błąd select()";