简介
写了一个UDP广播的代码。
IPv4一个,IPv6一个。
编译环境是linux C++11。
文件构成
ser.cpp用于发送广播。
cli.cpp用于接收广播。
build_cli.sh和build_svr.sh是编译脚本。
./cli 等待接收广播数据
./svr 执行发送广播
代码实现
IPv4, 发送广播
//使用的广播地址是"255.255.255.255",路由不会转发
int UDP_Controler::BroadCast()
{
if (m_ctl_type != ctl_unknowtype && m_ctl_type != ctl_broadcast_send)
{
LOGS << "Type error" << LOGE;
return -1;
}
int iset = 1;
if (setsockopt(m_local_fd, SOL_SOCKET, SO_BROADCAST, &iset, sizeof(iset)))
{
perror("setsockopt");
return -1;
}
char buff[MIN_BUFFSISE] = {0x00};
sprintf(buff, "%s", "@TEST GETJOB \r\n");
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("255.255.255.255");
addr.sin_port = htons(9100);
int res = sendto(m_local_fd, buff, strlen(buff), 0,
(sockaddr *)&addr, sizeof(addr));
if (res == -1)
{
perror("sendto");
return -1;
}
LOGS << "send broadcast msg:" << buff << "." << LOGE;
m_ctl_type = ctl_broadcast_send;
return 0;
}
IPv4, 接收广播
//使用的广播地址是"255.255.255.255",路由不会转发
int UDP_Controler::BroadCast_Recv()
{
if (m_ctl_type != ctl_unknowtype && m_ctl_type != ctl_broadcast_recv)
{
LOGS << "Type error" << LOGE;
return -1;
}
char buff[MIN_BUFFSISE] = {0x00};
sockaddr_in local_addr, addr;
socklen_t len = sizeof(sockaddr_in);
local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
local_addr.sin_port = htons(9100);
local_addr.sin_family = AF_INET;
if(bind(m_local_fd, (sockaddr*)&local_addr, len) == -1) {
perror("bind");
return -1;
}
int res = recvfrom(m_local_fd, buff, MIN_BUFFSISE, 0,
(sockaddr *)&addr, &len);
if (res == 0)
{
perror("recvfrom return 0");
return -1;
}
else if (res == -1)
{
perror("recvfrom return -1");
return -1;
}
LOGS << "recv broadcast msg:" << buff << ",from:" << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port) << LOGE;
m_ctl_type = ctl_broadcast_recv;
return res;
}
IPv6 ,发送广播
//唯有sockaddr 部分和IPv4不同
// "FF02::1"是IPv6链路本地广播地址,不可跨越路由器
int UDP_Controler::BroadCast()
{
if (m_ctl_type != ctl_unknowtype && m_ctl_type != ctl_broadcast_send)
{
LOGS << "Type error" << LOGE;
return -1;
}
int iset = 1;
if (setsockopt(m_local_fd, SOL_SOCKET, SO_BROADCAST, &iset, sizeof(iset)))
{
perror("setsockopt");
return -1;
}
char buff[MIN_BUFFSISE] = {0x00};
sprintf(buff, "%s", "FF02::1");
sockaddr_in6 addr;
addr.sin6_family = AF_INET6;
int res = inet_pton(AF_INET6, buff, &addr.sin6_addr);
if(res <= 0) {
perror("inet_pton");
return -1;
}
addr.sin6_port = htons(9100);
addr.sin6_scope_id = if_nametoindex("ens33");
bzero(buff,MIN_BUFFSISE);
sprintf(buff, "%s", "@TEST IPV6 GETJOB \r\n");
res = sendto(m_local_fd, buff, strlen(buff), 0,
(sockaddr *)&addr, sizeof(addr));
if (res == -1)
{
perror("sendto");
return -1;
}
LOGS << "send broadcast msg:" << buff << "." << LOGE;
m_ctl_type = ctl_broadcast_send;
return 0;
}
IPv6, 接收广播
//唯有sockaddr 不分和IPv4不同
// "FF02::1"是IPv6链路本地广播地址,不可跨越路由器文章来源:https://www.toymoban.com/news/detail-806741.html
int UDP_Controler::BroadCast_Recv()
{
if (m_ctl_type != ctl_unknowtype && m_ctl_type != ctl_broadcast_recv)
{
LOGS << "Type error" << LOGE;
return -1;
}
char buff[MIN_BUFFSISE] = {0x00};
sockaddr_in6 local_addr, addr;
socklen_t len = sizeof(sockaddr_in6);
local_addr.sin6_addr = in6addr_any;
local_addr.sin6_port = htons(9100);
local_addr.sin6_family = AF_INET6;
if(bind(m_local_fd, (sockaddr*)&local_addr, len) == -1) {
perror("bind");
return -1;
}
int res = recvfrom(m_local_fd, buff, MIN_BUFFSISE, 0,
(sockaddr *)&addr, &len);
if (res == 0)
{
perror("recvfrom return 0");
return -1;
}
else if (res == -1)
{
perror("recvfrom return -1");
return -1;
}
char addrv6[128] = { 0x00 };
inet_ntop(AF_INET6, &addr.sin6_addr , addrv6, 128 );
LOGS << "recv broadcast msg:" << buff << ",from:" << addrv6 << ":" << ntohs(addr.sin6_port) << LOGE;
m_ctl_type = ctl_broadcast_recv;
return res;
}
完整代码:
查看链接资源。文章来源地址https://www.toymoban.com/news/detail-806741.html
到了这里,关于[UDP] UDP广播的实现IPv4&IPv6的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!