关于双网卡绑定socket接收组播的问题

足球流氓 2017-03-24 12:44:34

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>

#define BUFLEN 1000
int
main (int argc, char **argv)

{
struct sockaddr_in peeraddr,ia;

int sockfd;
char recmsg[BUFLEN + 1];

unsigned int socklen, n;

struct ip_mreq mreq;


/* 创建 socket 用于UDP通讯 */

sockfd = socket (AF_INET, SOCK_DGRAM, 0);

if (sockfd < 0)

{ printf ("socket creating err in udptalk\n");

exit (1);

}

/* 设置要加入组播的地址 */

bzero(&mreq, sizeof (struct ip_mreq));


inet_pton(AF_INET,"226.1.1.1",&ia.sin_addr);//组播地址

/* 设置组地址 */

bcopy (&ia.sin_addr.s_addr, &mreq.imr_multiaddr.s_addr, sizeof (struct in_addr));

/* 设置发送和接收源主机的地址信息 */

// mreq.imr_interface.s_addr = htonl (INADDR_ANY);

//这样写是否能绑定到对应的网卡上
mreq.imr_interface.s_addr = inet_addr("192.168.2.110");



/* 把本机加入组播地址,即本机网卡作为组播成员,只有加入组才能收到组播消息 */

if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,sizeof (struct ip_mreq)) == -1)

{ perror ("setsockopt");

exit (-1);

}


socklen = sizeof (struct sockaddr_in);

memset (&peeraddr, 0, socklen);

peeraddr.sin_family = AF_INET;

peeraddr.sin_port = htons (9999);//组播端口

inet_pton(AF_INET, "226.1.1.1", &peeraddr.sin_addr); //组播地址

int opt = 1;
// sockfd为需要端口复用的套接字

setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));


/* 绑定自己的端口和IP信息到socket上 */

if (bind(sockfd, (struct sockaddr *) &peeraddr,sizeof (struct sockaddr_in)) == -1)

{ printf ("Bind error\n");

exit (0);

}


/* 循环接收网络上来的组播消息 */

for (;;)

{ bzero (recmsg, BUFLEN + 1);

n = recvfrom (sockfd, recmsg, BUFLEN, 0, (struct sockaddr *) &peeraddr, &socklen);

if (n < 0)

{
printf ("recvfrom err in udptalk!\n");

exit (4);

}

else
{ /* 成功接收到数据报 */

recmsg[n] = 0;

fflush(stdout);

printf ("peer:");

}


}



}


我的板子是通过pcie总线连接一个网络板卡上 网络板卡有2个独立的网卡 我是分别开2个socket绑定到2个网卡上收组播
比如组播地址226.1.1.1 端口9991 绑定到192.168.1.110的网卡上 226.1.1.2 端口9991绑定到192.168.2.110
现在2个程序运行后 2个 网口都连到交换机上 我的主机分别建立2个socket也连到交换机上向这2个组播地址发数据 但始终只有一个能接收到 就是默认路由的那个地址


我单独运行某一个都可以收到数据 就是2个一起连上只有一个能收到 这个是不是跟路由设置有关 对双网卡和路由这块确实不太了解 恳请大家看看问题了
...全文
982 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
足球流氓 2017-03-27
  • 打赏
  • 举报
回复
找到原因了 反向过滤导致的 跟代码没关系。。。。。
nswcfd 2017-03-27
  • 打赏
  • 举报
回复
IP_ADD_MEMBERSHIP -> ip_mc_join_group -> ip_mc_find_dev -> ip_dev_find -> local_table.tb_lookup 看起来跟路由还是有点关系的?
twintiger 2017-03-25
  • 打赏
  • 举报
回复
绑定网卡吧, mreq.imr_interface.s_addr = inet_addr("192.168.2.110"); 改成

#define INTERFACE1 "eth0"
#deinfe INTERFACE2 "eth1"
int interfaceindex;
if( (interfaceindex=if_nametoindex(INTERFACE1)) <=0 )
    perror("FFail to get eth0");
mreq.imr_interface = interfaceindex;

//同样的方法setsockopt 第二个socket。eth0 和 eth1是例子,用ifconfig可以看到两个网卡对应的接口名字
......
本文章将介绍如何使用RawSocket(原始套接字)开发网络嗅探器: 首先我们得了解什么是套接字,这个我就不多说,自己百度,百度百科比我说的好。 那么什么又是原始套接字呢,常用的套接字分为 SOCK_STREAM(流套接字) 用于TCPXY通讯。 SOCK_DGRAM(数据报套接字) 同于UDPXY通讯。 那么原始呢,他则是和名字一样原始套接字;举例:要想用流套接字进行一次TCP的发包,那么直接连接上对方服务器然后用Send就可以发送指定的内容,但其实发送的数据并不止你的那些内容,有一些东西是流套接字会给你自动补上的。TCP是属于IPXY的一个子XY,那么要发送一个TCP数据包就得加上(以太网XY报头这个先不提),IPXY的报头,和TCPXY报头,这些东西流套接字都会帮你处理,而原始套接字则不会(当然也可以设置让原始套接字构造IP报头)。原始套接字他有更多的用途,但相对来说也比流套接字或数据报套接字麻烦。 原始套接字还可以设置成允许接收本地所有的套接字数据。那么我们就利用这个功能来做嗅探器! 首先:1.使用  WSAStartup (合并短整数 (2, 2), WSADATA)  来初始化Winsocket服务 其参数有2个  第一个 (短整数型/双字节型):wVersionRequired  这个参数表明使用的winsock版本号,高位指定修订版本号,低位指定主版本号。第二个参数 WSADATA类型 用于接收Winsocket细节东西,咱不用管它。 //下面就不说那么详细了,源码里面全是注释,自己看。 2.然后使用socket (#AF_INET, #SOCK_RAW, #IPPROTO_IP)  来创建一个套接字   第一个参数应该是表明Internet地址格式反正只能固定这个,仅仅支持这个  参数2:表明要创建的是一个原始套接字,参数3:指定IPXY  IPXY包括其子XY TCP UDP 等。成功返回套接字句柄 3.  bind (s, addr, sizeof (addr))  将套接字绑定至指定网卡,参数1=套接字句柄    参数2为一个addr结构的值,该值表明要绑定的网卡IP及端口号 4.  ioctlsocket (Socket, 2550136833, 1) 将套接字的模式改变为允许接收所有数据 顺利完成上面的操作后咱就可以用Recv来接收数据包了,只要不断的调用Recv就OK。

23,114

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧