实现在多播组中进行数据的发送和接收
目录
实现在多播组中进行数据的发送和接收
函数文件信息
/*******************************************************************
* file name: udp_broad.c
* author : 17666589210@163.com
* date : 2024-06-04
* fileinfo : 设置一个多播组信息并进行绑定,可以向组中发送数据,也可以接收
* 组内的数据,并输出IP地址和获取到数据的当前时间
* note : None
* version : 1.0
* CopyRight (c) 2024 17666589210@163.com Right Reseverd
*******************************************************************/
相关头文件、宏定义以及全局变量
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <time.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#define MULTICAST_GROUP "225.1.1.1" // 多播组的ip地址
#define PORT 8888 // 端口号
#define MAX_BUF_SIZE 1024 // 缓冲数组大小
int sockfd; // 套接字文件的句柄
发送数据函数
/********************************************************************
*
* name : receive_thread
* function : 用于接收UDP协议数据的线程
* argument : none
* retval : 调用成功返回生成文件后的结果
* author : 17666589210@163.com
* date : 2024/06/04
* note : none
*
* *****************************************************************/
void *receive_thread(void *arg)
{
char databuf[MAX_BUF_SIZE];
char curr_time[20];
struct sockaddr_in source_addr;
socklen_t addr_len = sizeof(source_addr);
while (1)
{
int byte_recvdata = recvfrom(sockfd, databuf, sizeof(databuf), 0, (struct sockaddr *)&source_addr, &addr_len);
if (byte_recvdata < 0)
{
fprintf(stderr, "recv data error,errno:%d,%s\n", errno, strerror(errno));
continue;
}
databuf[byte_recvdata - 1] = '\0'; // 将获取数据包的数组中的末尾"\n"替换成"\0"
// char *destsource_ip = inet_ntoa(source_addr.sin_addr); // 获取目标源ip的网络字节序,转换为本地字节序
// 获取当前时间
time_t current_time = time(NULL);
struct tm *time_info;
time_info = localtime(¤t_time);
strftime(curr_time, sizeof(curr_time), "%Y-%m-%d %H:%M:%S", time_info);
printf("Message source >: [%s %s] packet data is >: [%s]\n", inet_ntoa(source_addr.sin_addr), curr_time, databuf);
bzero(databuf, sizeof(databuf));
}
}
发送数据函数
/********************************************************************
*
* name : send_thread
* function : 用于发送UDP协议数据的线程
* argument : none
* retval : 调用成功返回生成文件后的结果
* author : 17666589210@163.com
* date : 2024/06/04
* note : none
*
* *****************************************************************/
void *send_thread(void *arg)
{
struct sockaddr_in dest_addr;
socklen_t dest_addr_len = sizeof(dest_addr);
char mesdata[MAX_BUF_SIZE];
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
dest_addr.sin_addr.s_addr = inet_addr(MULTICAST_GROUP);
dest_addr.sin_port = htons(PORT);
while (1)
{
printf("Enter message to send: ");
fgets(mesdata, sizeof(mesdata), stdin); // 获取标准输入的数据存入缓存区中
sendto(sockfd, mesdata, strlen(mesdata), 0, (struct sockaddr *)&dest_addr, dest_addr_len);
usleep(100000);
}
}
主函数
int main(int argc, char *argv[])
{
// 1.创建UDP套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
fprintf(stderr, "udp socket error,errno:%d,%s\n", errno, strerror(errno));
exit(1);
}
// 2.设置多播组的端口和地址
struct sockaddr_in broad_addr;
memset(&broad_addr, 0, sizeof(broad_addr));
broad_addr.sin_family = AF_INET; // 协议族,是固定的
broad_addr.sin_port = htons(PORT); // 目标端口,必须转换为网络字节序
broad_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 目标地址 "192.168.64.xxx" 已经转换为网络字节序 INADDR_ANY
// 3.多播组信息绑定套接字
bind(sockfd, (struct sockaddr *)&broad_addr, sizeof(broad_addr));
// 4.加入多播组
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_GROUP);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
fprintf(stderr, "set socket error,errno:%d,%s\n", errno, strerror(errno));
exit(1);
}
printf("waiting data......\n");
// 5.创建接收和发送子线程
pthread_t recv_tid, send_tid;
pthread_create(&recv_tid, NULL, receive_thread, &sockfd); // 创建接收UDP信息数据的子线程
pthread_create(&send_tid, NULL, send_thread, &sockfd); // 创建发送UDP信息数据的子线程
// 6.等待子线程结束
pthread_join(recv_tid, NULL);
pthread_join(send_tid, NULL);
// 7.关闭套接字文件
close(sockfd);
return 0;
}