程序可以加入到一个多播组中并等待服务器发送数据包,并且程序还需要具有发送功能,如果收到数据包则把消息内容输出到终端。

/**************************************************************************************************************************************
*
*   字节序:数据以字节流的方式进行传输,底层都是采用二进制,字节流的顺序是由架构决定的,现在假设使用X86架构,是采用小端存储
*	网络字节序:
*	本地字节序:
*
*	大端存储:低地址存储高字节   当数据超过1个字节的时候才需要区分大端还是小端  假设int型 0x12345678   0x12  | 0x34  | 0x56 |  0x78
*	小端存储:低地址存储低字节   当数据超过1个字节的时候才需要区分大端还是小端  假设int型 0x12345678   0x78  | 0x56  | 0x34 |  0x12
*
*	设备A采用X86架构,所以设备A采用小端存储  待发送的数据 :0x12345678
*   设备B采用ARM架构,所以设备B采用大端存储  待接收的数据 :?
*
*   为了统一发送数据的格式,所以互联网传输的数据统一采用大端方式,为了方便开发,linux系统提供了转换的接口:htonl、htons、ntohl、ntohs
*
*   h :host  主机/本地
*   to:      转换
*   n :net   网络
*   l :long  长整型
*   s :short 短整型
*
*   htons:把本地字节序的一个短整型转换为网络字节序
*   htonl:把本地字节序的一个长整型转换为网络字节序
*   ntohs:把网络字节序的一个短整型转换为本地字节序
*   ntohl:把网络字节序的一个长整型转换为本地字节序
* ***********************************************************************************************************************************/
/**********************************************************************************
 *          
 *          file name:  brostcast.c
 *          author   :  A13326981379@163.com
 *          date     :  2024/06/03
 *          function :  程序可以加入到一个多播组中并等待服务器发送数据包,并且程序还需要具有发送功能,如果收到数据包则把消息内容输出到终端,
 *          note     :  None          
 *          CopyRight (c) 2024-2024  A13326981379@163.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 <time.h>
#include <unistd.h>
#include <pthread.h>
#define __PORT_SERVER 9999
#define GROUP_ADDR_01 "226.66.66.66"  
char senbuf[128] = "123456";
char buf[128] = {0};
char buffer[128] = {0};
/* *********************************************************************************
 *
 *          
 *     @function name:	getsmg
 *     @brief        :  接受多播组的信息
 *     @param        :  
 *                      @arg:线程函数的一个void *地址
 *     @retval       :
 *                      NULL
 *     @date         : 2024/06/03
 *     @version      :1.0 
 *     @note         : NULL
 * 
 *
 * *******************************************************************************/
void *getmsg(void *arg)
{
	int socketfd = *(int *)arg;
	// 接受别的机发送地址
	struct sockaddr_in source_addr;
	socklen_t addr_len = sizeof(source_addr);
	char *source_ip = inet_ntoa(source_addr.sin_addr);

	while (1)
	{
		sleep(2);
		recvfrom(socketfd,buf, sizeof(buf), 0, (struct sockaddr *)&source_addr,&addr_len); // 默认会阻塞
		char *source_ip = inet_ntoa(source_addr.sin_addr);
		printf(" [%s  %s] = %s\n",source_ip, buffer, buf);
		bzero(buf, sizeof(buf));
	}
	return NULL;
}
/* *********************************************************************************
 *
 *          
 *     @function name:	getsmg
 *     @brief        :  向多播组发送信息
 *     @param        :  
 *                      @arg:线程函数的一个void *地址
 *     @retval       :
 *                      NULL
 *     @date         : 2024/06/03
 *     @version      :1.0 
 *     @note         : NULL
 * 
 *
 * *******************************************************************************/
void *sedmsg(void *arg)
{
	struct sockaddr_in dest_addr;
	dest_addr.sin_family = AF_INET;			   // 协议族,是固定的
	dest_addr.sin_port = htons(__PORT_SERVER); // 服务器端口,必须转换为网络字节序
	dest_addr.sin_addr.s_addr = inet_addr(GROUP_ADDR_01);

	while (1)
	{
		sleep(2);
		sendto(*(int *)arg, senbuf, strlen(senbuf), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
	}
	return NULL;
}


int main(int argc,char *argv[])
{
     time_t timep;

     struct tm *p;

     time(&timep);

     p = gmtime(&timep);
	//将系统时间写入缓冲区
     sprintf(buffer, "%d年%d月%d日 %d:%d:%d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, 8 + p->tm_hour, p->tm_min, p->tm_sec);

	
	//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(__PORT_SERVER);			//目标端口,必须转换为网络字节序
	host_addr.sin_addr.s_addr   = htonl(INADDR_ANY);		//目标地址 "192.168.64.xxx"  已经转换为网络字节序  INADDR_ANY

	bind(udp_socket,(struct sockaddr *)&host_addr, sizeof(host_addr));

	//多播地址
	int iRet = -1;
    setsockopt(udp_socket, SOL_SOCKET, SO_REUSEADDR, &iRet, sizeof(iRet));
    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(GROUP_ADDR_01);               /* 多播组的IP地址               */
    mreq.imr_interface.s_addr = htonl(INADDR_ANY); 
	setsockopt(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));



	pthread_t snd;
	pthread_t get;
	
	pthread_create(&snd,NULL,sedmsg,&udp_socket);
	pthread_create(&get,NULL,getmsg,&udp_socket);

	pthread_join(snd, NULL);
	pthread_join(get, NULL);
	pthread_exit(NULL);
	

}

posted @   A-A-A-Ariana  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示