简体   繁体   中英

select() on Android always returns false

I'm currently setting up a UDP-based networking library in C++.

The way i intend to use them is to have two instances of the same application running.
One on Windows and one on Android.

The Android instance is supposed to send out a broadcast message which is received on Windows.
Then a unicast socket is opened on both ends and communication is started.

Right now, however, I'm testing with simple broadcasts in both directions.

According to what i've found in order to receive messages from a socket the bind() function must be called with the local IP address (in the form "192.168.xx") and the port number to listen on.

On windows i'm able to find this local IP address using the following code:

char* UDPSocketPC::getLocalAddress()
{
    hostent *thisHost = gethostbyname ( "" );
    char buf [100];
    _itoa_s ( **thisHost->h_addr_list, buf, 10 );
    return inet_ntoa ( *reinterpret_cast<struct in_addr * >(*thisHost->h_addr_list) );
    //returns an ip address in the form of "192.168.0.3"
}

On Android however, the gethostbyname function doesn't exist and neither does the hostent class.

What i'm using instead right now are things like INADDR_ANY (0.0.0.0), INADDR_BROADCAST (255.255.255.255) and INADDR_LOOPBACK (127.0.0.1). Neither of these addresses receive the broadcasts i'm sending.

All other things appear to be set up correctly.
On Windows i'm receiving broadcasts sent from Windows as well as from Android.
On Android i'm receiving neither.

The main difficulty with this question is that the vast majority of documentation online is either targeted at Unix sockets or at WinSock sockets, so it's quite difficult to find a good example of this for the NDK.

Thanks in advance for any help.

EDIT:

I've made some progress, and it looks like the problem I was having was actually related to my attempts to make the recvfrom () function non-blocking

Here is my implementation of the select() function on Windows:

fd_set sockets = fd_set ( );
sockets.fd_array [0] = socketPTR;
sockets.fd_count = 1;
fd_set empty = fd_set ( );
const timeval timeout = { timeoutSec, timeoutMicroSec };
return select ( 0, &sockets, &empty, &empty, &timeout ) > 0;

And here's how i did it on Android:

fd_set sockets = fd_set ( );
FD_ZERO ( &sockets );
FD_SET ( socketPTR, &sockets );
fd_set empty = fd_set ( );
FD_ZERO ( &empty );
timeval timeout = { timeoutSec, timeoutMicroSec };
return select ( 0, &sockets, &empty, &empty, &timeout ) > 0;

The Windows implementation does pretty much exactly what i would expect it to, it returns false when no data is available for reading, and true when there is at least one message in the queue.
However on Android it seems to always return false.

By temporarily removing the call from Android i am able to send and receive messages from both platforms on both platforms.
But now the call is blocking on Android (which isn't ideal since i want to have the thread doing other things while no data is available).

I will look for more information regarding the select() function on Android in order to get it actually working.

You are not supplying a value to the first parameter of select() . That parameter is ignored on Windows, but it is NOT ignored on other platforms. Per the documentation :

nfds is the highest-numbered file descriptor in any of the three sets, plus 1.

So, in your example, you need to set the parameter to socketPTR+1 .

Also, do not provide empty fd_set structs for unused parameters. Use NULL instead:

Each of the three file descriptor sets may be specified as NULL if no file descriptors are to be watched for the corresponding class of events.

Also, always use FD_ZERO() and FD_SET() , even on Windows. This helps to promote code portability across platforms that use different layouts for fd_set .

Try this code instead:

fd_set sockets;
FD_ZERO( &sockets );
FD_SET( socketPTR, &sockets );
timeval timeout = { timeoutSec, timeoutMicroSec };
return select ( socketPTR+1, &sockets, NULL, NULL, &timeout ) > 0;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM