嵌入式 Linux下进行广播包交互示例

服务器端也就是接受广播包:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <linux/in.h>
#include <stdlib.h>
/**
  广播接收端代码
 **/
#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){
		printf("=============================Recv Broadcast===================================\n");
		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",(char *)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);//将数据发送给客户端
					}
					
				}
				break;
		}
	}
	return;
}


客户端发送广播查找服务器:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <net/if.h>
 
/**
  客户端实现广播


 **/
#define IP_FOUND "IP_FOUND"
#define IP_FOUND_ACK "IP_FOUND_ACK"
#define IFNAME "eth0"
#define MCAST_PORT 9999
#define MAX_BROADCAST_NUM 16

int main(int argc,char*argv[]){
	int ret=-1;


	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;

	int sock=-1;
	sock=socket(AF_INET,SOCK_DGRAM,0);//建立数据报套接字
	if(sock<0){
		printf("HandleIPFound:sock init error\n");
		return;
	}


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

	bzero(&ifr, sizeof(ifr));
	//strcpy(ifr.ifr_name, "eth0");
	strncpy(ifr.ifr_name,IFNAME,strlen(IFNAME));

	//发送命令,获得网络接口的广播地址
	if(ioctl(sock,SIOCGIFBRDADDR,&ifr)==-1){
		perror("ioctl error");
		return;
	}

	//将获得的广播地址复制到broadcast_addr
	int so_broadcast=1;
	struct sockaddr_in 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));


	while(1)
	{
		sleep(1);
		printf("=====================================Send Broadcast========================================\n");
		//发送多次广播,看网络上是否有服务器存在
		int times = 1;
		int i=0;
		for(i=0;i<times;i++){//一共发送10次广播,每次等待2秒是否有回应
			//广播发送服务器地址请求
			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)){
						memset(buffer,0,1024);
						count=recvfrom(sock,buffer,1024,0,(struct sockaddr*)&from_addr,&from_len);//from_addr为服务器端地址
						strcpy((buffer+strlen(buffer)),"\0");
						
						printf("recvmsg is %s ,The length of recvmsg is %d\n",buffer,strlen(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));
						}
					}
					break;

			}
		}

	}
	return;
}
 

注意:

1、程序是死循环完成接收或者发送广播包

2、程序没有内存泄漏问题

3、程序没有接收乱码的问题服务器端运行效果:

=====================================Send Broadcast========================================
recvmsg is IP_FOUND_ACK ,The length of recvmsg is 12
found server IP is:10.10.2.59
Server Port:9999
=====================================Send Broadcast========================================
recvmsg is IP_FOUND_ACK ,The length of recvmsg is 12
found server IP is:10.10.2.59
Server Port:9999

客户端运行效果:

=============================Recv Broadcast===================================
ret=1
Client IP is 10.10.2.59
Client Send Port:33784
=============================Recv Broadcast===================================
ret=1
Client IP is 10.10.2.155
Client Send Port:38542

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值