udp 广播通信
基于全网段广播的代码示例,要点主要有两个:
(1)设置socket属性SO_BROADCAST
(2)发送方添加广播255.255.255.255的路由,不然会产生“Network is unreachable”错误
ip route add 255.255.255.255 dev eth0
示例代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define REMOTE_PORT 22222
#define LOCAL_PORT 55555
int main(int argc,char** argv)
{
int ret = 0, opt = 1, recv_fd, send_fd;
struct sockaddr_in local_addr, remote_addr;
recv_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
send_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(recv_fd < 0 || send_fd < 0)
{
perror("create socket err");
return -1;
}
ret = setsockopt(recv_fd,SOL_SOCKET,SO_BROADCAST,&opt,sizeof(opt));
if (ret)
{
perror("recv sock opt SO_BROADCAST err");
return -2;
}
ret = setsockopt(recv_fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
if (ret)
{
perror("recv sock opt SO_REUSEADDR err");
return -3;
}
ret = setsockopt(send_fd,SOL_SOCKET,SO_BROADCAST,&opt,sizeof(opt));
if (ret)
{
perror("send sock opt SO_BROADCAST err");
return -4;
}
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(LOCAL_PORT);
local_addr.sin_addr.s_addr = INADDR_ANY;
memset(&remote_addr, 0, sizeof(remote_addr));
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(REMOTE_PORT);
remote_addr.sin_addr.s_addr = inet_addr("255.255.255.255"); /* INADDR_BROADCAST */
ret = bind(recv_fd,(struct sockaddr*)&local_addr,sizeof(local_addr));
if(ret)
{
perror("recv sock bind err");
return -4;
}
while(1)
{
struct sockaddr_in client_addr;
socklen_t sock_len = sizeof(client_addr);
char *ip =NULL;
int port = 0;
char buf[1024] = {0};
/* receive */
memset(&client_addr, 0, sizeof(struct sockaddr_in));
client_addr.sin_family = AF_INET;
int recv_len = recvfrom(recv_fd, buf, sizeof(buf), 0,
(struct sockaddr*)&client_addr, &sock_len);
if (recv_len > 0)
{
ip = inet_ntoa(client_addr.sin_addr);
port = ntohs(client_addr.sin_port);
printf("recv from [%s][%d]: %s, len: %d\n", ip, port, buf, recv_len);
}
else
{
perror("recv err");
continue;
}
/* send */
int send_len = sendto(send_fd, buf, recv_len, 0,
(struct sockaddr*)&remote_addr,sizeof(remote_addr));
if (send_len != recv_len)
{
perror("send err");
}
else
{
ip = inet_ntoa(remote_addr.sin_addr);
port = ntohs(remote_addr.sin_port);
printf("send to [%s][%d]: %s, len: %d\n", ip, port, buf, send_len);
}
// sleep(1);
}
close(recv_fd);
close(send_fd);
return 0;
}