linux网络编程之广播详细代码及文档说明 -,Linux网络编程之广播

本文介绍了如何在Linux中通过UDP广播实现局域网内的服务器探测,展示了TCP与UDP在广播通信上的区别,重点在于使用广播功能进行一对多通信。通过客户端发送IP_FOUND广播并监听响应,服务器通过IP_FOUND_ACK回应,揭示了广播在技术应用场景中的实用性。
摘要由CSDN通过智能技术生成

1.概念

前面介绍的TCP,UDP都是单播方式,即一对一.而广播是一台主机向局域网内的所有主机发送数据。这时,同一网段的所有主机都能接收到数据。发送广播包的步骤大致如下:

(1)确定一个发送广播的接口,如eth0

(2)确定广播的地址,通过ioctl函数,请求码设置为SIOCGIFBRDADDR得到广播的地址

(3)使用这个广播地址进行广播

由于TCP协议是端到端的协议,在通信之前,必须建立连接,三次握手之后才能发送数据。而广播是一对多的通信,所以TCP不支持广播。在局域网内,广播通常用来探测服务器。

2. 探测服务器实例

这个例子通过在局域网内发送广播包,收到广播包的服务器,应答主机。这样,就能够探测到局域网内的服务器。

主机:

/**

客户端实现广播

**/

#define IP_FOUND "IP_FOUND"

#define IP_FOUND_ACK "IP_FOUND_ACK"

#define IFNAME "eth0"

#define MCAST_PORT 9999

int main(int argc,char*argv[]){

int ret=-1;

int sock=-1;

int so_broadcast=1;

struct ifreq ifr;

struct sockaddr_in broadcast_addr;//广播地址

struct sockaddr_in from_addr;//服务端地址

int from_len=sizeof(from_addr);

int count=-1;

fd_set readfd;//读文件描述符集合

char buffer[1024];

struct timeval timeout;

timeout.tv_sec=2;//超时时间为2秒

timeout.tv_usec=0;

sock=socket(AF_INET,SOCK_DGRAM,0);//建立数据报套接字

if(sock<0){

printf("HandleIPFound:sock init error\n");

return;

}

//将使用的网络接口名字复制到ifr.ifr_name中,由于不同的网卡接口的广播地址是不一样的,因此指定网卡接口

strncpy(ifr.ifr_name,IFNAME,strlen(IFNAME));

//发送命令,获得网络接口的广播地址

if(ioctl(sock,SIOCGIFBRDADDR,&ifr)==-1){

perror("ioctl error");

return;

}

//将获得的广播地址复制到broadcast_addr

memcpy(&broadcast_addr,&ifr.ifr_broadaddr,sizeof(struct sockaddr_in));

//设置广播端口号

printf("broadcast IP is:%s\n",inet_ntoa(broadcast_addr.sin_addr));

broadcast_addr.sin_family=AF_INET;

broadcast_addr.sin_port=htons(MCAST_PORT);

//默认的套接字描述符sock是不支持广播,必须设置套接字描述符以支持广播

ret=setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&so_broadcast,sizeof(so_broadcast));

//发送多次广播,看网络上是否有服务器存在

int times=10;

int i=0;

for(i=0;i //广播发送服务器地址请求

timeout.tv_sec=2;//超时时间为2秒

timeout.tv_usec=0;

ret=sendto(sock,IP_FOUND,strlen(IP_FOUND),0,(struct sockaddr*)&broadcast_addr,sizeof(broadcast_addr));

if(ret==-1){

continue;

}

//文件描述符清0

FD_ZERO(&readfd);

//将套接字文件描述符加入到文件描述符集合中

FD_SET(sock,&readfd);

//select侦听是否有数据到来

ret=select(sock+1,&readfd,NULL,NULL,&timeout);

switch(ret){

case -1:

break;

case 0:

printf("timeout\n");

break;

default:

//接收到数据

if(FD_ISSET(sock,&readfd)){

count=recvfrom(sock,buffer,1024,0,(struct sockaddr*)&from_addr,&from_len);//from_addr为服务器端地址

printf("recvmsg is %s\n",buffer);

if(strstr(buffer,IP_FOUND_ACK)){

printf("found server IP is:%s\n",inet_ntoa(from_addr.sin_addr));

//服务器端的发送端口号

printf("Server Port:%d\n",htons(from_addr.sin_port));

}

return;

}

break;

}

}

return;

}

服务器:

/**

广播服务器端代码

**/

#define IP_FOUND "IP_FOUND"

#define IP_FOUND_ACK "IP_FOUND_ACK"

#define PORT 9999

int main(int argc,char*argv[]){

int ret=-1;

int sock;

struct sockaddr_in server_addr;//服务器端地址

struct sockaddr_in from_addr;//客户端地址

int from_len=sizeof(struct sockaddr_in);

int count=-1;

fd_set readfd;//读文件描述符集合

char buffer[1024];

struct timeval timeout;

timeout.tv_sec=2;

timeout.tv_usec=0;

sock=socket(AF_INET,SOCK_DGRAM,0);//建立数据报套接字

if(sock<0){

perror("sock error");

return;

}

memset((void*)&server_addr,0,sizeof(struct sockaddr_in));

server_addr.sin_family=AF_INET;

server_addr.sin_addr.s_addr=htons(INADDR_ANY);

server_addr.sin_port=htons(PORT);

//将地址结构绑定到套接字上./

ret=bind(sock,(struct sockaddr*)&server_addr,sizeof(server_addr));

if(ret<0){

perror("bind error");

return;

}

while(1){

timeout.tv_sec=2;

timeout.tv_usec=0;

//文件描述符集合清0

FD_ZERO(&readfd);

//将套接字描述符加入到文件描述符集合

FD_SET(sock,&readfd);

//select侦听是否有数据到来

ret=select(sock+1,&readfd,NULL,NULL,&timeout);//侦听是否可读

printf("ret=%d\n",ret);

switch(ret){

case -1://发生错误

break;

case 0://超时

printf("timeout\n");

break;

default:

if(FD_ISSET(sock,&readfd)){

count=recvfrom(sock,buffer,1024,0,(struct sockaddr*)&from_addr,&from_len);//接收客户端发送的数据

//from_addr保存客户端的地址结构

if(strstr(buffer,IP_FOUND)){

//响应客户端请求

//打印客户端的IP地址

printf("Client IP is%s\n",inet_ntoa(from_addr.sin_addr));

//打印客户端的端口号

printf("Client Send Port:%d\n",ntohs(from_addr.sin_port));

memcpy(buffer,IP_FOUND_ACK,strlen(IP_FOUND_ACK)+1);

count=sendto(sock,buffer,strlen(buffer),0,(struct sockaddr*)&from_addr,from_len);//将数据发送给客户端

}

return;

}

break;

}

}

return;

}

说明: 由于默认的套接字是不支持广播的,所以必须设置套接字选项(setsockopt)来支持广播。接口的广播地址通过ioctl函数得到。广播是基于UDP协议的。MAC地址是FF:FF:FF:FF:FF:FF.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值