项目篇:基于UDP通信模型的网络聊天室

思维导图

基于UDP通信模型的网络聊天室

消息分类及数据包结构

服务器端

#include <head.h>
#define SER_PORT 8888
#define SER_IP "192.168.232.133"
typedef struct mb
{struct sockaddr_in cin;char name[20];struct mb *next;
}*member;
//群发消息
int send_to_all(int sfd,member head,const char *buf,size_t length)
{member p=head;while(p!=NULL){sendto(sfd,buf,length,0,(struct sockaddr*)&(p->cin),sizeof(p->cin));p=p->next;}return 0;
}
//增加成员
member add_member(member head,const char *data,struct sockaddr_in cin)
{member p=(member)malloc(sizeof(struct mb));p->cin=cin;strcpy(p->name,data);p->next=head;head=p;return head;
}
//删除成员
member del_member(member head,const char *name_point)
{member p=head;if(strcmp(p->name,name_point)==0){head=p->next;free(p);p=NULL;return head;}while(strcmp(p->name,name_point)!=0){p=p->next;}if(p->next==NULL){member q=head;while(q->next->next!=NULL){q=q->next;}free(p);p=NULL;q->next=NULL;return head;}member q=head;while(strcmp(q->next->name,name_point)!=0){q=q->next;}q->next=p->next;free(p);p=NULL;return head;
}int main(int argc, const char *argv[])
{int sfd=socket(AF_INET,SOCK_DGRAM,0);if(sfd==-1){perror("socket 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;}struct sockaddr_in cin;socklen_t socklen=sizeof(cin);printf("bind success\n");struct pollfd pfd[1024];pfd[0].fd=0;pfd[0].events=POLLIN;pfd[1].fd=sfd;pfd[1].events=POLLIN;int n=2;member head=NULL;while(1){int res=poll(pfd,n,-1);if(res==-1){perror("poll error:");return -1;}else if(res==0){printf("manbaout\n");return -1;}if(pfd[0].revents==POLLIN){//系统发送消息char buf[128]="";scanf("%s",buf);char sys_buf[200];sprintf(sys_buf,"***system***>>>%s",buf);send_to_all(sfd,head,sys_buf,sizeof(sys_buf));printf("系统发送消息\n");}if(pfd[1].revents==POLLIN){//接收消息char buf[200]="";recvfrom(pfd[1].fd,buf,sizeof(buf),0,(struct sockaddr*)&cin,&socklen);short *type_point = (short*)buf;switch(ntohs(*type_point)){case 1:{//接收到登录的消息char *data_point = buf+2;char buf[300]="";sprintf(buf,"**********%s已登录**********",data_point);send_to_all(sfd,head,buf,sizeof(buf));head=add_member(head,data_point,cin);printf("%s登录\n",data_point);break;}case 2:{//接收到普通的消息char *name_point=buf+2;char *data_point=name_point+strlen(name_point)+1;char buf[300]="";sprintf(buf,"%s>>>%s",name_point,data_point);send_to_all(sfd,head,buf,sizeof(buf));printf("%s发送消息\n",name_point);break;}case 3:{//接收到退出消息char *name_point=buf+2;char *data_point=name_point+strlen(name_point)+1;char endbuf[20]="";strcpy(endbuf,"quit");sendto(sfd,endbuf,sizeof(endbuf),0,(struct sockaddr*)&cin,sizeof(cin));del_member(head,name_point);char buf[300]="";sprintf(buf,"**********%s已下线**********",name_point);send_to_all(sfd,head,buf,sizeof(buf));printf("%s下线\n",name_point);break;}}}}close(sfd);return 0;
}

客户端

#include <head.h>
#define SER_PORT 8888
#define SER_IP "192.168.232.133"int login(int sfd,struct sockaddr_in sin,const char *name)
{char buf[200]="";short *type_point = (short*)buf;char *data_point = buf+2;*type_point=htons(1);strcpy(data_point,name);sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));return 0;
}
int main(int argc, const char *argv[])
{int sfd=socket(AF_INET,SOCK_DGRAM,0);if(sfd==-1){perror("socket 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);socklen_t socklen;printf("====================欢迎使用网络聊天室====================\n");printf("请输入姓名:");char name[20];scanf("%s",name);login(sfd,sin,name);pid_t pid;pid=fork();if(pid>0){//父进程,用于发消息char buf[128]="";short *type_point = (short*)buf;char *name_point = buf+2;strcpy(name_point,name);char *data_point=name_point+strlen(name_point)+1;while(1){scanf("%s",data_point);if(strcmp(data_point,"quit")==0){*type_point=htons(3);sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));break;}*type_point=htons(2);sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));}}else if(pid==0){//子进程,用于接收消息while(1){char buf[128];recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&socklen);if(strcmp(buf,"quit")==0){break;}printf("%s\n",buf);}}wait(NULL);close(sfd);return 0;
}

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

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

相关文章

使用双异步后,如何保证数据一致性?

目录 一、前情提要二、通过Future获取异步返回值1、FutureTask 是基于 AbstractQueuedSynchronizer实现的2、FutureTask执行流程3、get()方法执行流程 三、FutureTask源码具体分析1、FutureTask源码2、将异步方法的返回值改为Future<Integer>&#xff0c;将返回值放到new…

【Java】学习一门开发语言,从TA的Hello World开始

欢迎来到《小5讲堂》 大家好&#xff0c;我是全栈小5。 这是《Java》序列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对知识点的理解和掌握…

《WebKit 技术内幕》学习之七(3): 渲染基础

3 渲染方式 3.1 绘图上下文&#xff08;GraphicsContext&#xff09; 上面介绍了WebKit的内部表示结构&#xff0c;RenderObject对象知道如何绘制自己&#xff0c;但是&#xff0c;问题是RenderObject对象用什么来绘制内容呢&#xff1f;在WebKit中&#xff0c;绘图操作被定…

Android 基础技术——addView 流程

笔者希望做一个系列&#xff0c;整理 Android 基础技术&#xff0c;本章是关于 addView 在了解 addView 流程之前&#xff0c;先回答下以下几个问题&#xff1a; PhoneWindow是什么时候创建的&#xff1f; DectorView 是什么&#xff1f; DectorView 是什么时候创建的&#xf…

Kafka 问题排查

订单宽表数据不同步 事情的起因是专员在 ze app 上查不到订单了&#xff0c;而订单数据是从 mysql 的 order_search_info 查询的&#xff0c;order_search_info 表的数据是从 oracel 的 BZ_ORDER_INFO 表同步过来的&#xff0c;查不到说明同步有问题 首先重启&#xff0c;同步…

vue3相比vue2的效率提升

1、静态提升 2、预字符串化 3、缓存事件处理函数 4、Block Tree 5、PatchFlag 一、静态提升 在vue3中的app.vue文件如下&#xff1a; 在服务器中&#xff0c;template中的内容会变异成render渲染函数。 最终编译后的文件&#xff1a; 1.静态节点优化 那么这里为什么是两部分…

如何在Linux部署JumpServer堡垒机并实现远程访问本地服务

文章目录 前言1. 安装Jump server2. 本地访问jump server3. 安装 cpolar内网穿透软件4. 配置Jump server公网访问地址5. 公网远程访问Jump server6. 固定Jump server公网地址 前言 JumpServer 是广受欢迎的开源堡垒机&#xff0c;是符合 4A 规范的专业运维安全审计系统。JumpS…

IDEA中启动项目报堆内存溢出或者没有足够内存的错误

1.报错现象 java.lang.OutOfMemoryError: Java heap space 或者 Could not reserve enough space for object heap 2.解决办法 在运行配置中VM选项后加下面的配置&#xff1a; -server -XX:MaxHeapSize256m -Xms512m -Xmx512m -XX:PermSize128M -XX:MaxPermSize256m 3.JVM虚…

iOS开发调试神器:Reveal 24 功能介绍

Reveal 24 for Mac是一款功能强大的iOS应用界面调试工具&#xff0c;可以帮助用户浏览iOS应用层次结构&#xff0c;检查项目并立即解决渲染问题。以下是Reveal 24 for Mac的最新中文软件介绍&#xff1a; Reveal 24 for Mac拥有强大的编辑功能&#xff0c;用户可以在运行中的应…

QT第六天

要求&#xff1a;使用QT绘图&#xff0c;完成仪表盘绘制&#xff0c;如下图。 素材 运行效果&#xff1a; 代码&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPainter> #include <QPen>QT_BEGIN_NAMESPACE name…

Linux第30步_通过USB OTG将固件烧写到eMMC中

学习目的&#xff1a;在Win11中&#xff0c;使用STM32CubeProgrammer工具&#xff0c;通过USB OTG将固件烧写到eMMC中。 安装软件检查&#xff1a; 1、是否安装了JAVA; 2、是否安装了STM32CubeProgrammer工具; 3、是否安装 了DFU驱动程序; 4、是否安装了“Notepad”软件; …

Jupyter Notebook安装以及简单使用教程

Jupyter Notebook安装以及简单使用教程 本文章将&#xff0c;简要的讲解在已经拥有Python环境下如何进行Jupyter Notebook的安装。并且简短的介绍Jupyter Notebook的使用方法。 Jupyter Notebook是什么 Jupyter Notebook是一个基于Web的交互式计算环境&#xff0c;它支持多种…