我目前正在用C ++建立一个基于UDP的网络库。
我打算使用它们的方法是运行同一个应用程序的两个实例 一个在Windows上,另一个在Android上。
Android实例应该发送一个在Windows上收到的广播消息 然后在两端打开单播套接字并开始通信。
但是,现在,我正在测试两个方向的简单广播。
根据我发现的,为了从套接字接收消息,必须使用本地IP地址调用bind()函数(格式为" 192.168.x.x")以及要收听的端口号。
在Windows上,我可以使用以下代码找到此本地IP地址:
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"
}
在Android上,gethostbyname
功能不存在,hostent
类也不存在。
我现在使用的是INADDR_ANY
(0.0.0.0),INADDR_BROADCAST
(255.255.255.255)和INADDR_LOOPBACK
(127.0.0.1)。这些地址都没有收到我发送的广播。
其他所有内容似乎都设置正确 在Windows上,我接收从Windows和Android发送的广播 在Android上我没有收到。
这个问题的主要困难在于绝大多数在线文档都是针对Unix套接字或WinSock套接字,因此很难为NDK找到一个很好的例子。
提前感谢您的帮助。
编辑:
我已经取得了一些进展,看起来我遇到的问题实际上与我尝试使recvfrom ()
功能无阻塞有关
以下是我在Windows上select()
函数的实现:
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;
以下是我在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;
Windows实现几乎完全符合我的预期,当没有数据可供读取时返回false,当队列中至少有一条消息时返回true。 但是在Android上似乎总是返回false。
通过暂时从Android中删除呼叫,我可以在两个平台上从两个平台发送和接收消息 但是现在这个调用在Android上是阻塞的(这不是理想的,因为我想让线程做其他事情而没有数据可用)。
我会在Android上查找有关select()
功能的更多信息,以使其真正有效。
答案 0 :(得分:3)
您没有为select()
的第一个参数提供值。在Windows上忽略该参数,但在其他平台上不会忽略它。每the documentation:
nfds
是三组中任何一组中编号最大的文件描述符,加上1。
因此,在您的示例中,您需要将参数设置为socketPTR+1
。
此外,不要为未使用的参数提供空fd_set
结构。请改用NULL
:
如果没有为相应的事件类监视文件描述符,则可以将三个文件描述符集中的每一个指定为NULL。
此外,即使在Windows上,也始终使用FD_ZERO()
和FD_SET()
。这有助于促进跨fd_set
使用不同布局的平台的代码可移植性。
请尝试使用此代码:
fd_set sockets;
FD_ZERO( &sockets );
FD_SET( socketPTR, &sockets );
timeval timeout = { timeoutSec, timeoutMicroSec };
return select ( socketPTR+1, &sockets, NULL, NULL, &timeout ) > 0;