实现在多播组中进行数据的发送和接收

目录


实现在多播组中进行数据的发送和接收

函数文件信息

/*******************************************************************
 * 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(&current_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;
}
posted @ 2024-06-04 21:21  52017  阅读(28)  评论(0编辑  收藏  举报