UDP的socket绑定到IP地址后无法接受广播数据
来源:互联网 发布:百度 seo 编辑:程序博客网 时间:2024/05/21 17:40
由于考虑到我的程序要在多网卡的机器上运行,所以我将网卡的ip地址绑定到了socket
server_addr.sin_addr.s_addr = inet_addr(servIP);但是这样就无法收到广播数据?同时我也绑定到了一个广播地址接受时发现没次客户端来的数据都连续接受两次;请问是为什么?
以下是我的测试程序:
//server.cpp
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
char * host_name = "192.168.0.255";
int port = 10051;
int main(void)
{
struct sockaddr_in serv_addr,addr;
char buf[256];
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
perror("Error: socket";
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(host_name);//htonl(INADDR_ANY);//
int bd = bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in));
while(1)
{
int len = sizeof(serv_addr);
memset(&serv_addr, 0, len);
int ret = recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&serv_addr,(socklen_t*)&len);
printf("recv=%d buf=%s
",ret, buf);
printf("RecvieIP:%s Recive Port:%d
", inet_ntoa(serv_addr.sin_addr),
ntohs(serv_addr.sin_port));
ret = sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in));
}
}
//client.cpp
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
char * host_name = "192.168.0.255";
int port = 10051;
int main(void)
{
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
perror("Error: socket";
return -1;
}
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
serv_addr.sin_addr.s_addr = inet_addr(host_name);
int so_broadcast;
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &so_broadcast,
sizeof(so_broadcast));
char buf[256]="client .............";
sockaddr from ;
int len;
sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in));
while(1)
{
recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&serv_addr,(socklen_t*)&len);
printf("server buf= %s
",buf);
}
}
server_addr.sin_addr.s_addr = inet_addr(servIP);但是这样就无法收到广播数据?同时我也绑定到了一个广播地址接受时发现没次客户端来的数据都连续接受两次;请问是为什么?
以下是我的测试程序:
//server.cpp
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
char * host_name = "192.168.0.255";
int port = 10051;
int main(void)
{
struct sockaddr_in serv_addr,addr;
char buf[256];
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
perror("Error: socket";
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(host_name);//htonl(INADDR_ANY);//
int bd = bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in));
while(1)
{
int len = sizeof(serv_addr);
memset(&serv_addr, 0, len);
int ret = recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&serv_addr,(socklen_t*)&len);
printf("recv=%d buf=%s
",ret, buf);
printf("RecvieIP:%s Recive Port:%d
", inet_ntoa(serv_addr.sin_addr),
ntohs(serv_addr.sin_port));
ret = sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in));
}
}
//client.cpp
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
char * host_name = "192.168.0.255";
int port = 10051;
int main(void)
{
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
perror("Error: socket";
return -1;
}
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
serv_addr.sin_addr.s_addr = inet_addr(host_name);
int so_broadcast;
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &so_broadcast,
sizeof(so_broadcast));
char buf[256]="client .............";
sockaddr from ;
int len;
sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in));
while(1)
{
recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&serv_addr,(socklen_t*)&len);
printf("server buf= %s
",buf);
}
}
嗯,bind到网卡地址是不能接收广播包的
那你就别bind了呗
udp广播的递送规则是:
如果没有设置BLOADCASE选项的不递送。
如果bind端口不匹配不递送该套接口
如果绑定的不是INADDR_ANY话
那么必须BIND的地址和目的地址匹配才能递送:
也就是说你必须BIND一个广播地址或者绑定INADDR_ANY
第三
如果你的udp调用了connect
那么源地址和源端口不匹配也不递送
否则递送
你可以设置其中一个网卡DISABLE广播能力
.那你就别bind了呗
udp广播的递送规则是:
如果没有设置BLOADCASE选项的不递送。
如果bind端口不匹配不递送该套接口
如果绑定的不是INADDR_ANY话
那么必须BIND的地址和目的地址匹配才能递送:
也就是说你必须BIND一个广播地址或者绑定INADDR_ANY
第三
如果你的udp调用了connect
那么源地址和源端口不匹配也不递送
否则递送
你可以设置其中一个网卡DISABLE广播能力
fannyth
05-11-11, 13:36
看来我要重新考虑解决我问题的思路;我把问题再说一遍,大家看看有什么好的思路来解决。
由于考虑到我的程序要在多网卡的机器上运行,所以我希望socket既能接受广播的数据又能接受单播的数据。同时在接受广播数据时只接受一次。因为服务器是多网卡的;而我的客户端在启动时还不知道自己的ip地址;所以客户端发送的广播地址是255.255.255.255;所以我想是否可以用两个soket一个用来接受广播,同时自动进行包过虑。另一个用来接受单播数据?不知这样可以吗?会不会有什么影响?
由于考虑到我的程序要在多网卡的机器上运行,所以我希望socket既能接受广播的数据又能接受单播的数据。同时在接受广播数据时只接受一次。因为服务器是多网卡的;而我的客户端在启动时还不知道自己的ip地址;所以客户端发送的广播地址是255.255.255.255;所以我想是否可以用两个soket一个用来接受广播,同时自动进行包过虑。另一个用来接受单播数据?不知这样可以吗?会不会有什么影响?
Westwind
05-11-11, 14:04
你可以这样做。
2个udp socket
单播的那个socket bind INADDR_ANY并且设置SO_BROADCAST选项为0,此时他只接受单播数据报
广播那个socket bind 255.255.255.255,并且设置SO_BROADCASE选项为1,此时他只接受UDP广播。
为了防止接收到同一个广播的2分copy,如果两个网卡位于同一个子网,那么就用ifconfig命令disable其中一块网卡的BROADCAST标志,让其不能接受以太网广播。
你也可以使用ioctl的SIOCSIFFLAGS方法去掉一个接口的标志IFF_BROADCAST,使之不能接受以太网广播
2个udp socket
单播的那个socket bind INADDR_ANY并且设置SO_BROADCAST选项为0,此时他只接受单播数据报
广播那个socket bind 255.255.255.255,并且设置SO_BROADCASE选项为1,此时他只接受UDP广播。
为了防止接收到同一个广播的2分copy,如果两个网卡位于同一个子网,那么就用ifconfig命令disable其中一块网卡的BROADCAST标志,让其不能接受以太网广播。
你也可以使用ioctl的SIOCSIFFLAGS方法去掉一个接口的标志IFF_BROADCAST,使之不能接受以太网广播
Westwind
05-11-12, 00:27
谢谢,你说的很详细了,我可以试试;但我想如果设置另一块网卡不能接受广播数据,是否会对其它程序有影响?所以我想能自己在接受广播数据的同时做一个检测,检测收到的数据是否是指定网卡接受到的如果是则处理,否则丢弃;但不知道如何检测?同时对效率的影响有多大?
这个也有可能,至少存在一个socket api可以返回数据报的目的地址,
recvmsg
recvmsg是非SVR4系统的recv,recvfrom,readv的底层实现,在recvmsg之下就是syscall了。
不过这个函数挺复杂的,你需要学习该函数的用法,并且该函数是不可移植的,至少windows不提供该方法。
这个也有可能,至少存在一个socket api可以返回数据报的目的地址,
recvmsg
recvmsg是非SVR4系统的recv,recvfrom,readv的底层实现,在recvmsg之下就是syscall了。
不过这个函数挺复杂的,你需要学习该函数的用法,并且该函数是不可移植的,至少windows不提供该方法。
- UDP的socket绑定到IP地址后无法接受广播数据
- UDP的socket绑定到IP地址后无法接受广播数据
- htc无法接受udp广播
- python: tcp/ip学习、端口号、UDP的发送和接受数据、绑定端口号、模拟聊天室
- 同wifi环境下android设备自动获取socket服务端的ip地址和端口号的方法-UDP广播
- 分用udp接受的ip数据报
- Delphi用Socket IP/UDP局域网广播
- 通过UDP广播自动获取IP地址
- 对于Socket的UDP数据广播的重新认识
- UDP广播和接受
- 用UDP进行广播后绑定发送Json数据进行通讯
- Socket使用Udp广播收发数据
- Socket 进行UDP广播数据(GCDAsyncUdpSocket)
- Socket 进行UDP广播数据(GCDAsyncUdpSocket)
- BroadcastReceiver无法接受广播的原因之一
- 关于开机广播无法接受的问题
- Android应用被强制停止后无法接受广播解决方案
- Android应用被强制停止后无法接受广播解决方案
- 多网卡 socket 的bind问题
- BI更偏向技术还是业务?
- 快速幂求余模板
- Mongodb源码分析--主程序入口main()
- c/c++中delete/free 指针后,设置p=NULL的好处
- UDP的socket绑定到IP地址后无法接受广播数据
- TinyXml 修改指定节点和增加节点的做法
- hdoj1059
- iOS (ProjectName-info.plist) (ProjectName-Prefix.pch) 解析
- windows 和ubuntu 下 安装sts遇到的各种问题
- appletviewer如何传参数applet,如何命令方式关闭applet
- poj 1951 Extra Krunch
- css优先级阐述
- 设为首页和加入收藏的HTML js代码