嵌入式学习-网络编程-Day6

嵌入式学习-网络编程-Day6

一、思维导图

二、作业

1.基于UDP的网络聊天室(2024.1.21号前上交)

项目需求:
1.如果有用户登录,其他用户可以收到这个人的登录信息
2.如果有人发送信息,其他用户可以收到这个人的群聊信息
3.如果有人下线,其他用户可以收到这个人的下线信息
4.服务器可以发送系统信息

框架

在这里插入图片描述

效果图

在这里插入图片描述

服务器端实现

#include <myhead.h>
#define SER_IP "192.168.122.39"
#define SER_PORT 8888
typedef struct Node  //链表存储客户端的所有信息
{struct sockaddr_in cin;  //存储客户端的网络地址信息struct Node *next;
}*List;
typedef struct Message//消息结构体
{char type;char name[20];char text[128];
}msg_t;
struct sockaddr_in cin;  //客户端地址信息结构体//单链表节点创建函数
List create_node()
{List p=(List)malloc(sizeof(struct Node));if(NULL==p)return NULL;p->next=NULL;return p;
}
//客户端链表尾插
List insert_rear(List head,struct sockaddr_in cin)
{List s=create_node();if(NULL==s)return head;s->cin=cin;if(NULL==head){head=s;return s;}else{List p=head;while(p->next!=NULL)p=p->next;p->next=s;return head;}
}
//客户端接入服务器通知函数
void chat_all_join(List head,msg_t msg,int sfd)
{List p=head;char buf[50]="";while(p->next!=NULL){snprintf(buf,sizeof(buf),"[%s:%d]%s加入聊天室\n",inet_ntoa(p->cin.sin_addr),\ntohs(p->cin.sin_port),msg.name);sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&(p->cin),sizeof(p->cin));p=p->next;}
}
//客户端消息转发函数
void chat_all(List head,struct Message msg,int sfd,struct sockaddr_in cin)
{List p=head;char rbuf[200]="";while(p->next!=NULL){snprintf(rbuf,sizeof(rbuf),"[%s:%d]%s:%s\n",inet_ntoa(p->cin.sin_addr),\ntohs(p->cin.sin_port),msg.name,msg.text);sendto(sfd,rbuf,sizeof(rbuf),0,(struct sockaddr*)&(p->cin),sizeof(p->cin));p=p->next;}snprintf(rbuf,sizeof(rbuf),"[%s:%d]%s:%s\n",inet_ntoa(p->cin.sin_addr),\ntohs(p->cin.sin_port),msg.name,msg.text);sendto(sfd,rbuf,sizeof(rbuf),0,(struct sockaddr*)&(p->cin),sizeof(p->cin));}
//客户端发送退出消息函数
void chat_all_quit(List head,struct Message msg,int sfd)
{char wbuf[200]="";	List p=head;while(p->next!=NULL){snprintf(wbuf,sizeof(wbuf),"[%s:%d]%s:退出了聊天室\n",inet_ntoa(p->cin.sin_addr),\ntohs(p->cin.sin_port),msg.name);sendto(sfd,wbuf,sizeof(wbuf),0,(struct sockaddr*)&(p->cin),sizeof(p->cin));p=p->next;}snprintf(wbuf,sizeof(wbuf),"[%s:%d]%s:退出了聊天室\n",inet_ntoa(p->cin.sin_addr),\ntohs(p->cin.sin_port),msg.name);sendto(sfd,wbuf,sizeof(wbuf),0,(struct sockaddr*)&(p->cin),sizeof(p->cin));
}
//链表中删除该地址信息
List exit_chat(List head)
{if(head->next==NULL)//只有一个客户端时{free(head);head=NULL;return head;}List p=head;while(p->next!=NULL)  //两个以上客户端{if(memcmp(&(p->next->cin),&cin,sizeof(cin))==0)//找到p下一个节点地址信息符合的{List del=p->next;p->next=del->next;free(del);del=NULL;break;}else{p=p->next;}}return head;
}
int main(int argc, const char *argv[])
{//创建通信的套接字文件描述符int sfd=-1;if((sfd=socket(AF_INET,SOCK_DGRAM,0))==-1){perror("socket error");return -1;}//快速刷新端口号int reuse=-1;if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){perror("setsockopt error");return -1;}//给当前套接字绑定结构体信息struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(SER_PORT);sin.sin_addr.s_addr=inet_addr(SER_IP);if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("bind error");return -1;}//准备文件描述符容器fd_set readfds,tempfds;FD_ZERO(&readfds);FD_SET(0,&readfds);FD_SET(sfd,&readfds);int maxfd=sfd;//定义变量存放客户端地址信息结构体,及客户端消息struct sockaddr_in cin;socklen_t socklen=sizeof(cin);struct Message msg;List head=NULL;char buf[128]="";while(1){tempfds=readfds;if(select(maxfd+1,&tempfds,NULL,NULL,NULL)==-1){perror("select error");return -1;}//收到消息if(FD_ISSET(sfd,&tempfds)){recvfrom(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&cin,&socklen);switch(msg.type){case 'L':  //客户端加入{head=insert_rear(head,cin);  //尾插入链表chat_all_join(head,msg,sfd);		printf("[%s:%d]%s加入聊天室\n",inet_ntoa(cin.sin_addr),\ntohs(cin.sin_port),msg.name);};break;case 'C':  //客户端消息{chat_all(head,msg,sfd,cin);printf("[%s:%d]%s:%s\n",inet_ntoa(cin.sin_addr),\ntohs(cin.sin_port),msg.name,msg.text);};break;case 'Q':  //客户端退出{chat_all_quit(head,msg,sfd);printf("[%s:%d]%s退出聊天室\n",inet_ntoa(cin.sin_addr),\ntohs(cin.sin_port),msg.name);head=exit_chat(head);};break;default:printf("type error\ttype=%c\n",msg.type);return -1;}}//发送消息if(FD_ISSET(0,&tempfds)){memset(buf,0,sizeof(buf));fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1]='\0';char wbuf[56]="";snprintf(wbuf,sizeof(wbuf),"***system***%s\n",buf);List p=head;while(p!=NULL){sendto(sfd,wbuf,sizeof(wbuf),0,(struct sockaddr*)&(p->cin),sizeof(p->cin));p=p->next;}}}return 0;
}

客户端实现

#include <myhead.h>
#define SER_IP "192.168.122.39"
#define SER_PORT 8888
//#define CLI_IP ""
//#define CLI_PORT
struct Message
{char type;char name[20];char text[128];};
int main(int argc, const char *argv[])
{struct Message msg;//创建通信用套接字文件描述符int cfd=-1;if((cfd=socket(AF_INET,SOCK_DGRAM,0))==-1){perror("socket error");}//填写服务器的地址信息结构体struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(SER_PORT);sin.sin_addr.s_addr=inet_addr(SER_IP);//发送客户端的登录信息printf("请输入昵称:");fgets(msg.name,sizeof(msg.name),stdin);msg.name[strlen(msg.name)-1]='\0';msg.type='L';if(sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("sendto info error");return -1;}else{printf("加入聊天服务器成功\n");}//准备文件描述符容器fd_set readfds,tempfds;FD_ZERO(&readfds);FD_SET(0,&readfds);FD_SET(cfd,&readfds);int maxfd=cfd;while(1){tempfds=readfds;int res=select(maxfd+1,&tempfds,NULL,NULL,NULL);if(res==-1){perror("select error");return -1;}//发数据if(FD_ISSET(0,&tempfds)){memset(msg.text,0,sizeof(msg.text));read(0,msg.text,sizeof(msg.text));msg.text[strlen(msg.text)-1]='\0';//客户端退出if(strcmp(msg.text,"quit")==0){msg.type='Q';sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));printf("本机已下线\n");close(cfd);return 0;}//与其他客户端通信else{msg.type='C';sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));}}//收数据if(FD_ISSET(cfd,&tempfds)){char buf[128]="";//不接收服务器的地址信息结构体recvfrom(cfd,buf,sizeof(buf),0,NULL,NULL);printf("%s",buf);fflush(stdout);}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/636332.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LabVIEW振动数据采集与分析系统

在这个项目中&#xff0c; LabVIEW软件配合精确的硬件组件&#xff0c;以实现高效的振动数据采集和复杂信号分析。硬件方面&#xff0c;系统采用了PCB振动加速度传感器的高灵敏度传感器&#xff0c;以及NI9234型号的数据采集卡&#xff0c;确保了数据采集的高精度和可靠性。软件…

Leetcode刷题-(6~10)-Java+Python+JavaScript

算法题是程序员的基本功&#xff0c;也是各个大厂必考察的重点&#xff0c;让我们一起坚持写算法题吧 遇事不决&#xff0c;可问春风&#xff0c;春风不语&#xff0c;即是本心。 我们在我们能力范围内&#xff0c;做好我们该做的事&#xff0c;然后相信一切都事最好的安排就…

2024年对我懒这件事的弥补

一、回顾、前言 时光飞逝转眼2023年就“溜”走了&#xff0c;还记得我最后一次发博客是在2023.7.12 距离现在已经n天了&#xff0c;原因尽是懒&#xff01; 拜拜&#xff0c;我继续偷懒去咯。 咳咳&#xff0c;显然这不可能&#xff0c;当然为了弥补大家我这个大好人也是憋…

前端包管理工具

一、代码共享方案 npm 进行发布上传 npmregistrynpm 进行安装 二、npm 包管理工具 2.1 介绍 安装 node 的时候自动安装 node package manager&#xff1a;Node 包管理工具 可以通过 npm 安装说明已经上传到这个仓库里面了 npm 官网查看是否有发布&#xff1a;npmjs.org …

JAVAEE出街 网络编程(一)

网络编程 一. 网络编程二. 客户端与服务器2.1 一问一答2.2 一问多答2.3 多问一答2.4 多问多答 三. TCP与UDP的特点 一. 网络编程 网络编程本质上就是学习传输层给应用层提供的API&#xff0c;把数据交给传输层&#xff0c;通过一层层的封装将数据通过网卡传输出去。 二. 客户端…

html5实现好看的年会邀请函源码模板

文章目录 1.设计来源1.1 邀请函主界面1.2 诚挚邀请界面1.3 关于我们界面1.4 董事长致词界面1.5 公司合作方界面1.6 活动流程界面1.7 加盟支持界面1.8 加盟流程界面1.9 加盟申请界面1.10 活动信息界面 2.效果和源码2.1 动态效果2.2 源码目录结构 源码下载 作者&#xff1a;xcLei…

《WebKit 技术内幕》之四(4): 资源加载和网络栈

4.实践&#xff1a;高效的资源使用策略 4.1 DNS和TCP连接 DNS解析和TCP连接占用大量的时间&#xff0c;可以从以下几个方面优化&#xff1a; 减少连接的重定向&#xff0c;有些网页中使用了大量的重定向&#xff0c;可能还会有很多次重定向&#xff0c;这不仅要求浏览器建立…

使用 FFmpeg 轻松调整视频的大小/缩放/更改分辨率

在此 FFmpeg 教程中&#xff0c;我们学习使用 FFmpeg 的命令行工具更改视频的分辨率&#xff08;或调整视频的大小/缩放&#xff09;。 更改视频的分辨率&#xff08;也称为调整大小或缩放&#xff09;是视频编辑、处理和压缩中非常常见的操作。对于 ABR 视频流尤其如此&#…

HCIP BGP选路实验

拓扑图&IP划分如下&#xff1a; 第一步&#xff0c;配置IP&环回地址 以R1为例&#xff0c;R2~R8同理 interface GigabitEthernet 0/0/0 ip address 12.0.0.1 24 interface LoopBack 0 ip address 10.0.0.1 24 第二步&#xff1a;对AS200网段配置OSPF协议 以R2为例&a…

[C#]C# winform部署yolov8目标检测的openvino模型

【官方框架地址】 https://github.com/ultralytics/ultralytics 【openvino介绍】 OpenVINO&#xff08;Open Visual Inference & Neural Network Optimization&#xff09;是由Intel推出的&#xff0c;用于加速深度学习模型推理的工具套件。它旨在提高计算机视觉和深度学…

【使用 UCF101 数据集】C3D 模型准备与模型训练

一、前言 本文章将对 C3D 模型进行解析&#xff0c;对里面的模型结构进行详解&#xff0c;最后使用UCF101 数据集对该模型进行实战&#xff0c;在进行推理时能够正确识别出未知视频中里面正确的类别。 二、目录 三、相关内容 四、详细介绍 【使用 UCF101 数据集】C3D 模型准…

HCIA——20应用层:C/S、P2P、peer

学习目标&#xff1a; 计算机网络 1.掌握计算机网络的基本概念、基本原理和基本方法。 2.掌握计算机网络的体系结构和典型网络协议&#xff0c;了解典型网络设备的组成和特点&#xff0c;理解典型网络设备的工作原理。 3.能够运用计算机网络的基本概念、基本原理和基本方法进行…

基于LabVIEW的压力传感器测试系统

摘要 现在各类压力传感器已广泛应用于各种工业自控环境&#xff0c;对压力传感器的研究 及应用&#xff0c;既可以体现一个国家的科技发展水平&#xff0c;又可以提升国家的综合国力&#xff0c;还 可以在丰富、方便和智能化人们的生活方面做出重要的贡献。而针对不同仪器组 成…

电脑监视软件(2024年最新电脑监控软件推荐)

在当今数字化的时代&#xff0c;电脑已经成为了我们生活和工作中不可或缺的工具。然而&#xff0c;随着电脑使用的普及&#xff0c;人们对于电脑安全的关注也日益增强。 为了保护个人隐私和企业机密&#xff0c;电脑监视软件应运而生。 本文将为您介绍2024年最新电脑监控软件的…

GO 中高效 int 转换 string 的方法与高性能源码剖析

文章目录 使用 strconv.Itoa使用 fmt.Sprintf使用 strconv.FormatIntFormatInt 深入剖析1. 快速路径处理小整数2. formatBits 函数的高效实现 结论 Go 语言 中&#xff0c;将整数&#xff08;int&#xff09;转换为字符串&#xff08;string&#xff09;是一项常见的操作。 本文…

MySQL---单表查询综合练习

创建emp表 CREATE TABLE emp( empno INT(4) NOT NULL COMMENT 员工编号, ename VARCHAR(10) COMMENT 员工名字, job VARCHAR(10) COMMENT 职位, mgr INT(4) COMMENT 上司, hiredate DATE COMMENT 入职时间, sal INT(7) COMMENT 基本工资, comm INT(7) COMMENT 补贴, deptno INT…

linux切换root用户su - root和su root的区别

这里说一下login shell和 no login shell的区别 通过tty客户端登陆的shell就是login shell&#xff0c;通过在图形界面使用ctrlshiftt的方式新建的shell是no login shell login shell 主要读取两个配置文件/etc/profile和~/.bash_profile no login shell 读取的文件和顺序为&am…

手把手教你薅熊链Berachain测试网空投

Berachain&#xff0c;这名字响当当&#xff01;是基于流动性证明的高性能区块链&#xff0c;结合了Tendermint和流动性共识证明&#xff0c;还采用了Celestia作为DA层。这速度快、成本低、确定性高&#xff0c;简直就是未来的大热门&#xff01;你知道吗&#xff1f;这家公司可…

金融——规避容易造成金融系统性风险的项目

金融的关联性太强&#xff0c;容易造成很多社会问题&#xff0c; 改变&#xff0c;必须建立在有效规避风险之上 蚂蚁金服上市被叫停的原因&#xff1f; 答&#xff1a; p2p造成哪些恶劣影响&#xff1f; 答&#xff1a; 信用体系 和 抵押体系 都各自存在优劣&#xff1f; 答…

AI写作软件哪个好?国内AI写作软件排行榜前十名

近年来&#xff0c;AI写作软件的出现为写作领域提供更多的便利和资源。这些软件利用机器学习和自然语言处理等技术&#xff0c;能够自动生成文章、写作建议和编辑指导&#xff0c;为写作者提供了极大的便利。然而&#xff0c;市场上的AI写作软件琳琅满目&#xff0c;究竟哪些软…