我有一个客户端在同一台机器上加入两个不同的多播组(相同的端口号)。在客户端,我使用epoll来监听两个套接字。 服务器尝试将组播消息发送到第一组。但是,epoll会在两个套接字上接收数据。是因为套接字在同一台机器上并使用相同的端口吗?请建议
代码段:
/* Client code to join multicast group */
multicastPort = "4321";
/* Resolve the multicast group address */
hints.ai_family = PF_UNSPEC;
hints.ai_flags = AI_NUMERICHOST;
if ((status = getaddrinfo(group_ip_address, NULL, &hints, &multicastAddr)) != 0)
{
perror("\nError g.");
}
hints.ai_family = multicastAddr->ai_family;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; /* Return an address we can bind to */
if ( getaddrinfo(NULL, multicastPort, &hints, &localAddr) != 0 )
perror("\nError f.");
/* Create socket for receiving datagrams */
if ( (sd = socket(localAddr->ai_family, localAddr->ai_socktype, 0)) < 0 )
perror("socket() failed");
/* lose the pesky "Address already in use" error message */
if (setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(int)) == -1)
perror("setsockopt");
/* Bind to the multicast port */
if ( bind(sd, localAddr->ai_addr, localAddr->ai_addrlen) != 0 )
perror("bind() failed");
struct ip_mreq multicastRequest; /* Multicast address join structure */
/* Specify the multicast group */
memcpy(&multicastRequest.imr_multiaddr,
&((struct sockaddr_in*)(multicastAddr->ai_addr))->sin_addr,
sizeof(multicastRequest.imr_multiaddr));
/* Accept multicast from any interface */
multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
/* Join the multicast address */
if ( setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest)) != 0 )
perror("setsockopt() failed");
/* Create a datagram socket on which to receive. */
==================================================
/* client code to listen on epoll sockets*/
int fd_id= multicast_join(lo,group_ip);
//sprintf(display,"Listening to group %s ip address %s\n", grp_name, grp_ip_address);
sprintf(display,"Listening to group %s and ip %s\n", grp_name, grp_ip_address);
PRINT(display);
if(fd_id > 0){
ADD_CLIENT_IN_LL(client_info,grp_name,group_ip,fd_id);
event->data.fd = fd_id;
char buf[30];
sprintf(buf,"fd_id %d",fd_id);
PRINT(buf);
event->events = EPOLLIN|EPOLLET;
status = epoll_ctl(efd, EPOLL_CTL_ADD, fd_id, event);
if ( status == -1)
{
perror("\nError while adding FD to epoll event.");
exit(0);
}
答案 0 :(得分:0)
如果在同一个IP和端口上打开了两个UDP套接字,则两个套接字都会收到到达的所有多播数据包。如果单播数据包到达,则实现是否定义了一个或另一个或两者是否接收到数据包。
如果您想知道传入数据包的目标IP地址,您需要设置IP_PKTINFO
套接字选项并使用recvmsg
代替recvfrom
来获取此附加数据
// sock is bound AF_INET socket, usually SOCK_DGRAM
// include struct in_pktinfo in the message "ancilliary" control data
setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt));
// the control data is dumped here
char cmbuf[0x100];
// the remote/source sockaddr is put here
struct sockaddr_in peeraddr;
// if you want access to the data you need to init the msg_iovec fields
struct msghdr mh = {
.msg_name = &peeraddr,
.msg_namelen = sizeof(peeraddr),
.msg_control = cmbuf,
.msg_controllen = sizeof(cmbuf),
};
recvmsg(sock, &mh, 0);
for ( // iterate through all the control headers
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mh);
cmsg != NULL;
cmsg = CMSG_NXTHDR(&mh, cmsg))
{
// ignore the control headers that don't match what we want
if (cmsg->cmsg_level != IPPROTO_IP ||
cmsg->cmsg_type != IP_PKTINFO)
{
continue;
}
struct in_pktinfo *pi = CMSG_DATA(cmsg);
// at this point, peeraddr is the source sockaddr
// pi->ipi_spec_dst is the destination in_addr
// pi->ipi_addr is the receiving interface in_addr
}