我已经在Windows和Linux中创建了IPv6 UDP服务器。 我在此处附加了相同的源代码以供查看。
此代码正在接收特定IPv6地址以及WINDOWS中的in6addr_any
上的数据包。
但是,当我在linux上移植此代码时,仅当我设置sin.sin6_addr = in6addr_any;
时,它才会接收数据包。
但是当我设置为inet_pton(AF_INET6, "2001:db8:21:333:250:baff:fed6:abe2", &sin.sin6_addr);
时,它不会接收任何数据包,而在Windows中,这两种情况都可以接收。
附件的源代码已成功编译,没有警告。 请帮助我理解为什么这种行为仅在Linux中而不是Windows中是观察者。
源代码:-
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
typedef struct
{
int i32AddressFamily;
int i32Type;
int i32Protocol;
}Socket_Pkt_t;
int sid;
int num;
uint8_t g_u8RxBuf[MAX_MPDU] = { 0 };
uint8_t g_pstSrc[MAX_MPDU] = { 0 };
int main(void)
{
struct sockaddr_in6 sin = { 0 };
struct in6_addr stAddress = { 0 };
struct ipv6_mreq mreq;
Socket_Pkt_t stSocketPkt;
fd_set stReadFds = {0};
struct timeval stSelectTimeout = {0};
struct sockaddr_in6 stSin = {0};
socklen_t stSinLen = sizeof(stSin);
int32_t i32RcvBytes = 0;
long i32Max = 0;
int reuseaddr = 1;
stSocketPkt.i32AddressFamily = AF_INET6;
stSocketPkt.i32Type = SOCK_DGRAM;
stSocketPkt.i32Protocol = IPPROTO_UDP;
sid = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
inet_pton(AF_INET6, "ff0e::bac0", &mreq.ipv6mr_multiaddr);
mreq.ipv6mr_interface = if_nametoindex("eth0");
num = setsockopt(sid, IPPROTO_IPV6, IPV6_JOIN_GROUP, (const char *)&mreq,sizeof(mreq));
//num = setsockopt(sid, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,sizeof(reuseaddr));
memset(&sin, 0 ,sizeof(sin));
sin.sin6_family = AF_INET6;
sin.sin6_port = htons(47808);
//inet_pton(AF_INET6, "2001:db8:21:333:250:baff:fed6:abe2", &sin.sin6_addr.__in6_u.__u6_addr8[]);
//sin.sin6_scope_id = 0x0e;
sin.sin6_addr = in6addr_any;
//2001:db8:21:333:12c3:7bff:fe4e:9edb
inet_pton(AF_INET6, "2001:db8:21:333:250:baff:fed6:abe2", &sin.sin6_addr);
num = bind(sid, (const struct sockaddr *) &sin,sizeof(struct sockaddr_in6));
if(num < 0)
{
reuseaddr = errno;
return -1;
}
/* calculate and save the time */
stSelectTimeout.tv_sec = 1000 / 1000;
stSelectTimeout.tv_usec = 1000 * (1000 - stSelectTimeout.tv_sec * 1000);
i32Max = sid;
while(1)
{
/* initialize the stReadFds to null */
FD_ZERO(&stReadFds);
/* add socket descriptor to stReadFds */
FD_SET(sid, &stReadFds);
num = select((int32_t)i32Max + 1, &stReadFds, NULL, NULL, &stSelectTimeout);
if(num > 0)
{
if(FD_ISSET(sid, &stReadFds))
{
/* clear read file descriptor */
FD_CLR(sid, &stReadFds);
FD_ZERO(&stReadFds);
i32RcvBytes = recvfrom(sid, (void *)g_u8RxBuf, 1506,
0, (struct sockaddr *) &stSin, &stSinLen);
/* copy address i.e. from where the data is received */
memcpy(g_pstSrc, &stSin, stSinLen);
printf("packet received ...\r\n");
}
}
else
{
/* clear read file descriptor */
FD_CLR(sid, &stReadFds);
//FD_CLR(BIP_GetSocketId_For_BroadComm(), &stReadFds);
FD_ZERO(&stReadFds);
}
}
return 0;
}