1.UDP发送端代码udp_send.c
//发送组播消息
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef struct udpData {
uint32_t type;
uint32_t length;
char srcIp[32];
uint32_t status;
} udpData_t;
int main(int arg, char * args[])
{
//可执行文件传参
//判断执行参数是否满足
if(arg != 3)
{
printf("请传递组播ip,及要绑定的端口号\n");
return -1;
}
//创建UDP socket
int udp_socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_socket_fd == -1)
{
printf("create socket failed ! error message :%s\n", strerror(errno));
return -1;
}
//地址信息
struct sockaddr_in dest_addr = {0};
dest_addr.sin_family = AF_INET;
int dest_port = 0;
char dest_ip[32] = {0};
udpData_t send_data;
dest_port = atoi(args[2]); //设置目的IP端口
dest_addr.sin_port = htons(dest_port); //网络通信都使用大端格式
dest_addr.sin_addr.s_addr = inet_addr(args[1]); //32位的整形
printf("test type:\n");
scanf("%d",&send_data.type);
send_data.type = htonl(20);
printf("test length:\n");
scanf("%d",&send_data.length);
send_data.length = htonl(send_data.length);
printf("test srcIp:\n");
scanf("%s",send_data.srcIp);
printf("test status:\n");
scanf("%d",&send_data.status);
send_data.status = htonl(send_data.status);
if (sendto(udp_socket_fd, (void *)&send_data, sizeof(send_data), 0, (struct sockaddr *) &dest_addr, sizeof(dest_addr)) == -1)
{
printf("sendto failed ! error message :%s\n", strerror(errno));
return -1;
}
//关闭socket
close(udp_socket_fd);
bzero(&send_data, sizeof(send_data));
return 0;
}
2.UDP接收端代码udp_recv.c
//组播消息接收
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
typedef struct udpData {
uint32_t type;
uint32_t length;
char srcIp[32];
uint32_t status;
} udpData_t;
int main(int argc,char *argv[])
{
//可执行文件传参
//判断执行参数是否满足
if(argc != 3)
{
printf("请传递组播ip,及要绑定的端口号\n");
return -1;
}
//将接收到的端口号并转换为int型
int port = atoi(argv[2]);
if( port < 1025 || port > 65535 )//0-1024供系统使用,最大可到65535
{
printf("端口号范围应在1025~65535");
return -1;
}
//创建udp socket 使用IPv4协议,UDP数据报,0:默认属性
int udp_socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if(udp_socket_fd < 0 )
{
perror("creat socket fail\n");
return -1;
}
//加入组播,组播地址224.0.0.0~239.255.255.255
struct ip_mreq mul = {0};
mul.imr_multiaddr.s_addr = inet_addr(argv[1]); //设置组播地址
mul.imr_interface.s_addr = inet_addr("0.0.0.0");
int ret = setsockopt(udp_socket_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mul, sizeof(mul));
if(ret < 0)
{
perror("set sock opt fail\n");
return -1;
}
else
{
printf("已经加入组:[%s:%d], 等待接收组消息。。。\n", argv[1], port);
}
//设置UDP的地址并绑定
struct sockaddr_in addr = {0}; //地址信息存放
addr.sin_family = AF_INET; //使用IPv4协议
addr.sin_port = htons(port); //网络通信都使用大端格式
addr.sin_addr.s_addr = inet_addr("0.0.0.0"); //32位的整形
ret = bind(udp_socket_fd, (struct sockaddr*)&addr, sizeof(addr));
if(ret < 0)
{
perror("bind fail:");
return -1;
}
struct sockaddr_in s_addr={0}; //定义一个缓冲区 存放对方的IP地址信息
int len = sizeof(s_addr);
char buf[1024] = {0};//消息缓冲区
udpData_t rec_data;
//接收UDP数据
while(1)
{
recvfrom(udp_socket_fd, &rec_data, sizeof(rec_data), 0, (struct sockaddr *)&s_addr, &len);
printf("[IP:%s,PORT:%d]", inet_ntoa(s_addr.sin_addr), ntohs(s_addr.sin_port)); //打印消息发送者的IP信息
printf("type = %d, length = %d, srcip = %s, status = %d\n", ntohl(rec_data.type), ntohl(rec_data.length), rec_data.srcIp, ntohl(rec_data.status));
if(strcmp(buf, "e") == 0)
{
break;
}
bzero(&rec_data, sizeof(rec_data));
}
}
3.运行结果
此功能主要调试十进制数据收发,相较于字符串收发的区别在于发送端需要借助htonl()函数进行转换,接收端需要借助ntohl()函数进行转换。此功能调试借鉴了其他博主分享的一些知识,得以调试成功,十分感谢!