【linux高级程序设计】(第十五章)UDP网络编程应用 2

时间:2021-07-20 03:52:49

UDP广播通信

单播:一对一,TCP和UDP均可完成

广播:只能UDP完成。广播时发送方只发送一个数据包,但是网络上的交换机默认转发广播数据包到所有端口。路由器默认不转发任何广播数据包。故广播在局域网范围内。

组播:只有UDP可以完成。发送消息到同一个组播组的主机。视频电话、视频会议多采用。

广播IP地址:主机号全1。网络号正常

广播MAC地址:全1,即FF:FF:FF:FF:FF:FF

广播数据帧格式

【linux高级程序设计】(第十五章)UDP网络编程应用 2

处理过程:

网卡驱动程序对比自己的MAC地址与目的MAC地址,发现是广播MAC地址,统一接收并交给OS(IP层)。

IP层判断IP地址与自己是否一致。发现为IP地址为当前网段的广播地址,交给传输层

传输层根据端口,如果有对应的端口交给应用程序处理。否则丢弃数据包。

不管主机是否有进程接收广播消息,广播消息一定会被网卡收到并交个操作系统处理。会造成网络主机负担。

设置socket可以发送广播消息

int yes = ;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));

接收端绑定地址信息时,需要制定接收任意地址信息的数据包。

例子:

发送端广播一段信息,接收端接收。

注意:setsockopt为广播的目的应该是告知MAC地址为FF:FF:FF:FF:FF:FF 而广播的IP地址需要我们自己写上。即(网络号:全1主机号)。通过ifconfig获取。

发送端

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<netinet/tcp.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/time.h> int main(int argc, char **argv)
{
struct sockaddr_in s_addr;
int sock;
int addr_len;
int len;
char buff[];
int yes;
//UDP 创建socket
if((sock = socket(AF_INET, SOCK_DGRAM, )) == -)
{
perror("socket");
exit(EXIT_FAILURE);
}
else
{
printf("create socket.\n\r");
}
//设置socket为可发送广播消息
yes = ;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes)); s_addr.sin_family = AF_INET;
s_addr.sin_port = htons();
if(argv[])
{
s_addr.sin_addr.s_addr = inet_addr(argv[]); //参数1 广播地址
}
else
{
printf("input sever ip!\n");
exit();
}
addr_len = sizeof(s_addr);
strcpy(buff, "hello message");
//发送消息
len = sendto(sock, buff, strlen(buff), , (struct sockaddr *)&s_addr, addr_len);
if(len < )
{
printf("\n\rsend error.\n\r");
exit(EXIT_FAILURE);
}
printf("send success.\n\r");
return ;
}

接收端

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<netinet/tcp.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/time.h> int main(int argc, char **argv)
{
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
int sock;
socklen_t addr_len;
int len;
char buff[];
//创建socket UDP
if((sock = socket(AF_INET, SOCK_DGRAM, )) == -)
{
perror("socket");
exit(EXIT_FAILURE);
}
else
{
printf("create socket.\n\r");
}
memset(&s_addr, , sizeof(struct sockaddr_in)); s_addr.sin_family = AF_INET;
s_addr.sin_port = htons();
s_addr.sin_addr.s_addr = INADDR_ANY;
//绑定IP地址
if((bind(sock, (struct sockaddr *)&s_addr, sizeof(s_addr))) == -)
{
perror("bind");
exit(EXIT_FAILURE);
}
else
{
printf("bind address to socket.\n\r");
}
addr_len = sizeof(c_addr);
while()
{
//阻塞方式接收数据
len = recvfrom(sock, buff, sizeof(buff) - , , (struct sockaddr *)&c_addr, &addr_len);
if(len < )
{
perror("recvfrom");
exit(EXIT_FAILURE);
}
buff[len] = '\0';
printf("recive come from %s:%d message:%s\n\r", inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port), buff);
}
return ;
}

【linux高级程序设计】(第十五章)UDP网络编程应用 2

【linux高级程序设计】(第十五章)UDP网络编程应用 2