/**************************************************************************************************************************************** file name:multicast.c* author :momolyl@126.com* date :2024/06/04* brief :小组实现,小组中的每位成员都需要设计程序,要求程序可以加入到一个多播组中并等待服务器发送数据包,* 并且程序还需要具有发送功能,如果收到数据包则把消息内容输出到终端,* 消息内容格式 [消息来源IP 消息时间 ] : 消息内容* note :运行多播可执行文件 ./multicast 服务器端口 多播组地址** CopyRight (c) 2024 momolyl@126.com All Right Reseverd* ***********************************************************************************************************************************/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <time.h>// 接受消息线程
void *pthreadrecv_task(void *argv)
{// 1.创建UDP套接字int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);if (udp_socket == -1){fprintf(stderr, "udp socket error,errno:%d,%s\n", errno, strerror(errno));exit(1);}// 2.需要先绑定服务器的端口和地址struct sockaddr_in host_addr;host_addr.sin_family = AF_INET; // 协议族,是固定的host_addr.sin_port = htons(atoi("9999")); // 目标端口,必须转换为网络字节序host_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 目标地址 "192.168.64.xxx" 已经转换为网络字节序 INADDR_ANYbind(udp_socket, (struct sockaddr *)&host_addr, sizeof(host_addr));// 3.调用recvfrom等待接收数据,并且接收客户端的网络信息char buf[128] = {0};struct sockaddr_in client;socklen_t client_len = sizeof(client);// 2.获取当前系统时间const char *weekday[] = {"日", " 一", " 二", "三", "四", "五", "六"};char timebuf[128] = {0};time_t CurrentTime;while (1){time(&CurrentTime);struct tm *time = localtime(&CurrentTime);sprintf(timebuf, "%d年 %02d月 %02d日 星期%s %02d:%02d:%02d", time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,weekday[time->tm_wday], time->tm_hour, time->tm_min, time->tm_sec);recvfrom(udp_socket, buf, sizeof(buf), 0, (struct sockaddr *)&client, &client_len); // 默认会阻塞printf("[消息来源:%s 当前时间:%s]:%s\n", inet_ntoa(client.sin_addr), timebuf, buf);bzero(buf, sizeof(buf));bzero(timebuf, sizeof(timebuf));}
}int main(int argc, char *argv[])
{char timebuf[128] = {0};pthread_t pthreadrecv;pthread_create(&pthreadrecv, NULL, pthreadrecv_task, NULL);// 检查参数有效性(多播组地址:224.6.6.6 端口:9999)if (argc != 3){fprintf(stderr, "argument is invaild ,errno:%d,%s\n", errno, strerror(errno));exit(1);}// 1.创建UDP套接字int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);if (udp_socket == -1){fprintf(stderr, "udp socket error,errno:%d,%s\n", errno, strerror(errno));exit(1);}// 加入多播组struct ip_mreqn mutipcast;struct in_addr imr_multiaddr;mutipcast.imr_multiaddr.s_addr = inet_addr("224.6.6.6");mutipcast.imr_address.s_addr = inet_addr("192.168.64.230");mutipcast.imr_ifindex = 0;setsockopt(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mutipcast, sizeof(mutipcast));// 设置广播属性int optval = 1;setsockopt(udp_socket, SOL_SOCKET, SO_BROADCAST, (void *)&optval, 4);// 2.向目标主机发送消息,需要设置目标端口和目标地址char buf[128] = "HELLO WORLD";struct sockaddr_in dest_addr;dest_addr.sin_family = AF_INET; // 协议族,是固定的dest_addr.sin_port = htons(atoi(argv[1])); // 服务器端口,必须转换为网络字节序dest_addr.sin_addr.s_addr = inet_addr(argv[2]); // 服务器地址 "192.168.64.xxx"while (1){// 3.向多播组发送内容sendto(udp_socket, buf, strlen(buf), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));sleep(5);}return 0;
}
运行结果: