/**
* author : [email protected]
* @brief : 程序可以加入到一个多播组中并等待服务器发送数据包,并且程序还需要具有发送功能,如果收到数据包则把消息内容输出到终端
* @date : 2024/06/06
* @version : 1.0
* @note : none
* CopyRight (c) 2023-2024 [email protected] All Right Reseverd
*/
#include <stdio.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <time.h>
#include <pthread.h>
#define MULTICAST_ADDR "224.88.88.88" //多播IP地址
#define PORT 9999 //多播端口
//编译 gcc xxx.c -o xxx -pthread
//运行 ./xxx 自身服务器端口
//定义全局变量用于接收UDP套接字
int udp_socket;
/**
* @function name: client
* @brief : 线程任务,客户端可向多播服务端发送消息
* @param : @arg : 创建线程是传递给client的参数,如无需求则填写NULL
* @date : 2024/06/06
* @version : 1.0
* @note : none
*/
//客户端任务
void *client(void *arg)
{
//2.向目标主机发送消息,需要设置目标端口和目标地址(绑定自身作为客户端)
char buffer[128] = {0};
struct sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET; //协议族,是固定的
dest_addr.sin_port = htons(PORT); //服务器端口,必须转换为网络字节序
dest_addr.sin_addr.s_addr = inet_addr(MULTICAST_ADDR); //服务器IP地址
bind(udp_socket,(struct sockaddr *)&dest_addr, sizeof(dest_addr));//绑定服务器和端口
while(1)
{
printf("请输入内容:");
scanf("%s",buffer);
//3.发送客户端的上线时间
sendto(udp_socket,buffer,strlen(buffer),0, (struct sockaddr *)&dest_addr,sizeof(dest_addr));
}
}
/**
* @function name: main
* @brief : 服务端可接收来自客户端发送的消息
* @param : @argc : 终端输入参数的个数
: @argv[] : 终端输入的参数
* @date : 2024/06/06
* @version : 1.0
* @note : none
*/
int main(int argc,char *argv[])
{
//检查参数有效性
if (argc != 2)
{
fprintf(stderr, "argument is invaild ,errno:%d,%s\n",errno,strerror(errno));
exit(1);
}
//1.创建UDP套接字
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;
struct ip_mreqn mreq;
host_addr.sin_family = AF_INET; //协议族,是固定的
host_addr.sin_port = htons(atoi(argv[1])); //目标端口,必须转换为网络字节序
host_addr.sin_addr.s_addr = htonl(INADDR_ANY); //已经转换为网络字节序INADDR_ANY
bind(udp_socket,(struct sockaddr *)&host_addr, sizeof(host_addr));
//加入多播组
mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_ADDR);
mreq.imr_address.s_addr= htonl(INADDR_ANY); // 或者指定网络接口地址
mreq.imr_ifindex = 0;
setsockopt(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
//创建客户端线程
pthread_t hostser;
pthread_create(&hostser,NULL,client,NULL);
//3.调用recvfrom等待接收数据,并且接收客户端的网络信息
char buf[128] = {0};
struct sockaddr_in client;
socklen_t client_len = sizeof(client);
while(1)
{
recvfrom(udp_socket,buf,sizeof(buf), 0 ,(struct sockaddr *)&client,&client_len); //默认会阻塞
// 输出消息内容
time_t now = time(NULL);
printf("client ip is [%s] time:%s %s\n", inet_ntoa(client.sin_addr),ctime(&now),buf);
bzero(buf,sizeof(buf));
}
return 0;
}
标签:多播,UDP,addr,协议,struct,udp,client,include,socket
From: https://www.cnblogs.com/lwj294/p/18234602