广播的发送
流程
- 创建socket
- 设置套接字选项(在默认情况下,UDP套接字文件不允许发送广播,需要设置套接字文件为允许发送广播的模式;)
- 发送数据(将目的地址IP设置为广播地址,同时需要设置端口(接收主机通过端口号来接收,否则数据直接发送到UDP层就会丢失),调用sendto函数发送数据)
相关api
#include <sys/types.h>
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen); /* 获取套接字文件选项 */
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
/*
功能:设置套接字文件的选项
参数:
参数1:sockfd表示的套接字文件的文件描述符;
参数2:level表示的是协议的层序号
SOL_SOCKET 通用套接字属性协议层
IPPROTO_TCP TCP协议层
IPPROTO_IP IP协议层
参数3:optname表示的是对应协议层中的选项名称
SO_BROADCAST 允许套接字发送广播
参数4:optval表示选项的值,由于不同选项的参数不同,所以使用void *指针来实现。
参数5:optlen表示参数4只想空间的大小。
返回值:
成功返回0,失败返回-1且修改errno的值。
*/
实例
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
int sockfd;
int optval;
int ret;
struct sockaddr_in broadcastaddr;
char buf[128];
/* 创建UDP数据报套接字文件 */
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
perror("socket");
return -1;
}
/* 允许发送广播 */
optval = 1;/* 1 = 允许, 0 = 不允许 */
ret = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));
if (ret == -1)
{
perror("setsockopt");
return -1;
}
/* 发送广播数据 */
/* 初始化广播地址空间结构体 */
broadcastaddr.sin_family = AF_INET;
broadcastaddr.sin_port = htons(8888);
broadcastaddr.sin_addr.s_addr = inet_addr("192.168.0.255");
while(1)
{
fgets(buf, sizeof(buf), stdin);
/* 发送数据 */
ret = sendto(sockfd, buf, sizeof(buf), 0, (const struct sockaddr *)&broadcastaddr, sizeof(broadcastaddr));
if (ret == -1)
{
perror("sendto");
return -1;
}
}
}
广播的接收
流程
- 创建socket
- 设置接收主机的IP地址和端口号(需要和发送广播的端口号保持一致)
- 接收广播数据
实例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
int sockfd;
int ret;
struct sockaddr_in srvaddr;
struct sockaddr_in cltaddr;
socklen_t addrlen = sizeof(cltaddr);
char buf[128];
/* 创建UDP数据报套接字文件 */
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
perror("socket");
return -1;
}
/* 初始化服务器地址空间结构体 */
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(8888);
srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
/* 设置服务器的IP地址和端口号 */
ret = bind(sockfd, (const struct sockaddr *)&srvaddr, sizeof(srvaddr));
if (ret == -1)
{
perror("bind");
return -1;
}
printf("init UDP server sucess\n");
while(1)
{
/* 接收数据 */
ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&cltaddr, &addrlen);
if (ret == -1)
{
perror("recvfrom");
return -1;
}
/* 解析得到对端的IP地址:端口 -> 数据 */
printf("%s:%d -> buf : %s\n", inet_ntoa(cltaddr.sin_addr), ntohs(cltaddr.sin_port), buf);
}
}
网友评论