楼主最近遇到了一个多网卡广播的问题,问题描述如下:
服务器上安装了多个网卡,当程序广播到255.255.255.255这个地址上时,
只有主网卡网段上的机子可以收到UDP数据,其他网段并不能收到数据.
针对这个问题,解决方案为:发送时绑定网卡的ip地址,比如两个网卡的ip地址为:192.168.23.2(主)
和10.20.30.4 广播时需要用两个socket分别绑定这两个ip,再进行发送.
如果两个网卡ip的第一位是一样的比如192.168.23.2(主)和192.169.24.2则可以通过设置
子网掩码255.0.0.0来将两个网络设置成一个内网从而进行广播,不需要本文中介绍的这么麻烦.
实现代码如下:
class UDPSender
{
public:
UDPSender()
{
m_sock=-1;
}
~UDPSender(){}
bool SetRecvAddr(const char* addr,int port)
{
int sock=socket(AF_INET,SOCK_DGRAM,0);
if(sock<0)
{
cout<<"socket init error!"<<endl;
return false;
}
sockaddr_in addrSrv;
addrSrv.sin_addr.s_addr=inet_addr(addr);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(port);
if((addrSrv.sin_addr.s_addr>>24)==0xff)//if addr end with 255 then broadcast
{
GetLocalIP();
isBroadCast=true;
string local=findlocalIp(addr);
if(local.compare("")==0)
{
cout<<"find local ip error!"<<endl;
return false;
}
sockaddr_in addrSrvLocal;
addrSrvLocal.sin_addr.s_addr=inet_addr(local.c_str());
addrSrvLocal.sin_family=AF_INET;
addrSrvLocal.sin_port=0;//unuse
if(bind(sock,(sockaddr *)&addrSrvLocal,sizeof(addrSrvLocal))!=0)
{
cout<<"bind local ip error!"<<endl;
return false;
}
int opval=1;
addrSrv.sin_addr.s_addr=htonl(INADDR_BROADCAST);
setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&opval,sizeof(opval));
}
m_sock=sock;
m_sockaddr=addrSrv;
return true;
}
void Send(char* buf,int bufsize)
{
sendto(m_sock,buf,bufsize,0,(struct sockaddr*)&m_sockaddr,sizeof(sockaddr));
}
private:
void GetLocalIP()
{
FILE *fstream=NULL;
char buf[128];
memset(buf,0,sizeof(buf));
string cmd="/sbin/ifconfig |grep \"inet addr\"|awk \'{print $2}\'|awk -F \':\' \'{print $2}\'";// cmd: /sbin/ifconfig |greo "inet addr"|awk '{print $2}'|awk -F ':' '{print $2}'
if(NULL==(fstream=popen(cmd.c_str(),"r")))
{
cout<<"ifconfig exec error"<<endl;
return;
}
while(NULL != fgets(buf,sizeof(buf),fstream))
{
buf[strlen(buf)-1]='\0';//erase \n
LocalIP.push_back(buf);
}
return;
}
string findlocalIp(string BCast)
{
if(LocalIP.size()==0)
{
cout<<"local ip empty"<<endl;
return "";
}
int pos=BCast.find_first_of(".");
if(pos<0)
{
cout<<"distination IP address format error!"<<endl;
return "";
}
BCast[pos]=0;//compare first byte
vector<string>::iter it=LocalIP.begin();
for(;it!=LocalIP.end();it++)
{
string local=*it;
pos=local.find_first_of(".");
if(pos<0)
{
cout<<"local IP address format error"<<endl;
return "";
}
local[pos]=0;
if(strcmp(BCast.c_str(),local.c_str())==0)
{
return *it;
}
}
return "";
}
vector<string> LocalIP;
bool isBroadCast;
int m_sock;
sockaddr_in m_sockaddr;
}
下面是main函数
void main()
{
UDPSender sender1,sender2;
if(sender1.setRecvAddr("192.168.23.255",9999)==true)
{
cout<<"BroadCasting 192.168.23 ..."
Sender.Send("hello",sizeof("hello"));
}
if(sender2.setRecvAddr("10.20.30.255",9998)==true)
{
cout<<"BroadCasting 10.20.30 ..."
Sender2.Send("hello",sizeof("hello"));
}
return;
}