写了一个UDP广播的代码。
IPv4一个,IPv6一个。
编译环境是linux C++11。
ser.cpp用于发送广播。
cli.cpp用于接收广播。
build_cli.sh和build_svr.sh是编译脚本。
./cli 等待接收广播数据
./svr 执行发送广播
//使用的广播地址是"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;
}
//使用的广播地址是"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;
}
//唯有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;
}
//唯有sockaddr 不分和IPv4不同
// "FF02::1"是IPv6链路本地广播地址,不可跨越路由器
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;
}
完整代码:
查看链接资源。