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

cnblogs 2024-06-10 12:45:01 阅读 77

目录

  • 题目
  • 分析
  • 代码
  • 结果

题目


小组实现,小组中的每位成员都需要设计程序,要求程序可以加入到一个多播组中并等待服务器发送数据包,并且程序还需要具有发送功能,如果收到数据包则把消息内容输出到终端, 消息内容格式 [消息来源IP 消息时间 ] : 消息内容

分析


1.发送端需设置套接字的广播属性,使用setsockopt()函数,第三个参数需添加SO_BROADCAST;

2.接收端需设置同一端口号并加入组播地址,才能接受同组发送的信息,也需要使用setsockopt()函数,第三个参数需添加IP_ADD_MEMBERSHIP。

代码


/***********************************************************************************

*

*file name:udp_client.c

*author : cnzycwp@126.com

*date : 2024/06/04

*function : 该案例是小组实现,小组中的每位成员都需要设计程序,要求程序可以加入到一个

*多播组中并等待服务器发送数据包,并且程序还需要具有发送功能,如果收到数据

*包则把消息内容输出到终端,消息内容格式 [消息来源IP 消息时间 ]:消息内容

* note : None

* version :

*

*CopyRight (c) 2023-2024 cnzycwp@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 <sys/types.h> /* See NOTES */

#include <sys/socket.h>

/***********************************************************************************/

/************************************全局变量***************************************/

int udp_socket;//UDP套接字

/***********************************************************************************/

/*************************************结构体****************************************/

typedef struct lcd_time

{

int year;//年

int mon;//月

int mday;//日

int wday;//星期

int hour;//时

int min;//分

int sec;//秒

}LcdTime;

/***********************************************************************************/

/***********************************************************************************

*

*name :GetTime

*function : 调用此函数可获取开发板的时间

*param :

*none

*

*retval : char *

*author : cnzycwp@126.com

*date : 2024/06/04

* note : None

* version :

*

* *********************************************************************************/

//获取开发板时间

char *GetTime()

{

//申请堆内存并定义一个记录LCD硬件时间的结构体指针

LcdTime *tstm = (LcdTime *)calloc(1,sizeof(LcdTime));

char * tstime = (char *)calloc(1,sizeof(char) * 32);

//错误处理

if (NULL == tstm)

{

printf("calloc for time failed\n");

return NULL;

}

//4.获取当前系统时间,并把时间转换为特定格式“yy年mm月dd日 星期x tt:mm:ss”

time_t Tseconds = time(NULL);

struct tm *ft = localtime(&Tseconds);

tstm->year = (ft->tm_year) + 1900; //年从1900年开始

tstm->mon = (ft->tm_mon) + 1; //月份从0开始

tstm->mday = (ft->tm_mday);

tstm->wday = (ft->tm_wday);

tstm->hour = (ft->tm_hour);

tstm->min = (ft->tm_min);

tstm->sec = (ft->tm_sec);

sprintf(

tstime,

"%d年%02d月%02d日,星期%d,%02d:%02d:%02d",

tstm->year,

tstm->mon,

tstm->mday,

tstm->wday,

tstm->hour,

tstm->min,

tstm->sec

);

//fwrite(data_buffer,BUFFRSIZE,1,fp);

return tstime;

}

/***********************************************************************************

*

*name :recv_udp_msg

*function : 子线程的任务函数,该函数用于接收服务器发送的数据包

*param :

*none

*

*retval : none

*author : cnzycwp@126.com

*date : 2024/06/04

* note : None

* version :

*

* *********************************************************************************/

void *recv_udp_msg(void *arg)

{

//1.需要先绑定服务器的端口和地址

struct sockaddr_in host_addr;

host_addr.sin_family = AF_INET; //协议族,是固定的

host_addr.sin_port = htons(60000);//目标端口,必须转换为网络字节序

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));

//3.调用recvfrom等待接收数据,并且接收客户端的网络信息

char buf[128] = {0};

char *p = (char *)calloc(1,sizeof(char) * 32) ;

struct sockaddr_in client;

socklen_t client_len = sizeof(client);

while(1)

{

p = GetTime();

recvfrom(udp_socket,buf,sizeof(buf), 0 ,(struct sockaddr *)&client,&client_len); //默认会阻塞

printf("[%s,%s]:%s\n",inet_ntoa(client.sin_addr),p,buf);

bzero(buf,sizeof(buf));

}

}

// 运行客户端可执行文件 ./xxx 服务器端口 服务器地址

int main(int argc,char *argv[])

{

//检查参数有效性

// if (argc != 3)

// {

// 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);

}

//设置组播选项

struct ip_mreqn mreqn;

mreqn.imr_multiaddr.s_addr = inet_addr("226.66.66.66");//组地址

mreqn.imr_address.s_addr = htonl(INADDR_ANY);//本地地址 inet_addr("192.168.64.97")

mreqn.imr_ifindex = 0;//接口索引

setsockopt(udp_socket,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn));

//设置广播属性

int opt = 1;

setsockopt(udp_socket,SOL_SOCKET,SO_BROADCAST,&opt,sizeof(opt));

//设置组播属性

// setsockopt(udp_socket,IPPROTO_IP,IP_MULTICAST_TTL,&opt,sizeof(opt));

//2.创建子线程

pthread_t recv_thread;

pthread_create(&recv_thread,NULL,recv_udp_msg,NULL);

//2.向目标主机发送消息,需要设置目标端口和目标地址

char buf[128] = {0};

struct sockaddr_in dest_addr;

dest_addr.sin_family = AF_INET; //协议族,是固定的

dest_addr.sin_port = htons(60000);//服务器端口,必须转换为网络字节序

dest_addr.sin_addr.s_addr = inet_addr("226.66.66.66");//服务器地址 "192.168.64.xxx"

//3.发送客户端的上线时间

while(1)

{

scanf("%s",buf);

sendto(udp_socket,buf,strlen(buf),0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));

}

return 0;

}

结果


image



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。