网络聊天室
一、项目要求
利用UDP协议,实现一套聊天室软件。服务器端记录客户端的地址,客户端发送消息后,服务器群发给各个客户端软件。
问题思考
- 客户端会不会知道其它客户端地址?
UDP客户端不会直接互连,所以不会获知其它客户端地址,所有客户端地址存储在服务器端。
- 有几种消息类型?
- 登录:服务器存储新的客户端的地址。把某个客户端登录的消息发给其它客户端。
- 聊天:服务器只需要把某个客户端的聊天消息转发给所有其它客户端。
- 退出:服务器删除退出客户端的地址,并把退出消息发送给其它客户端。
- 服务器如何存储客户端的地址?
数据结构可以选择线性数据结构
链表节点结构体:
struct node{
struct sockaddr_in addr;//data memcmp
struct node *next;
};
消息对应的结构体(同一个协议)
typedef struct msg_t
{
int type;//'L' C Q enum un{login,chat,quit};
char name[32];//用户名
char text[128];//消息正文
}MSG_t;
int memcmp(void *s1,void *s2,int size)
- 客户端如何同时处理发送和接收?
客户端不仅需要读取服务器消息,而且需要发送消息。读取需要调用recvfrom,发送需要先调用gets,两个都是阻塞函数。所以必须使用多任务来同时处理,可以使用多进程或者多线程来处理。
二、程序流程图
服务器端
客户端

三、代码实现
server.c代码部分:
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<string.h>
#include<stdlib.h>
#include <sys/wait.h>
#include<dirent.h>
#include<sys/stat.h>
#include<signal.h>
#include <pthread.h>struct sockaddr_in serveraddr,caddr;
enum type_t//枚举
{Login,Chat,Quit,
};
typedef struct MSG
{char type;//L C Qchar name[32];//char text[128];//
}msg_t;typedef struct NODE//链表
{struct sockaddr_in caddr;struct NODE *next;
}node_t;node_t *create_node(void)//建头节点
{node_t *p=(node_t *)malloc(sizeof(node_t));if(p==NULL){perror("malloc err");return NULL;}p->next=NULL;return p;}
void do_login(int ,msg_t ,node_t *,struct sockaddr_in);//登录的函数
void do_chat(int ,msg_t ,node_t *,struct sockaddr_in);//群聊的函数
void do_quit(int ,msg_t ,node_t *,struct sockaddr_in);//退出函数
int main(int argc, char const *argv[])
{if(argc !=3){printf("Usage:./a.out <port>\n");return -1;}//创建UDP套接字int sockfd = socket(AF_INET,SOCK_DGRAM,0);if(sockfd<0){perror("socket err");exit(-1);}//填充服务器网络信息结构体serveraddr.sin_family=AF_INET;serveraddr.sin_port=htons(atoi(argv[2]));serveraddr.sin_addr.s_addr=inet_addr(argv[1]);socklen_t len = sizeof(caddr);//定义保存客户端网络信息的结构体//绑定套接字和服务器网络信息的结构体bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));printf("bind ok!\n");msg_t msg;node_t *p=create_node();while(1){if(recvfrom(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&caddr,&len)<0){perror("recvfrom err");return -1;}if(msg.type==Login){strcpy(msg.text,"以上线");printf("ip:%s pord:%d name:%s\n",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port),msg.name);printf("状态:%s\n",msg.text);do_login(sockfd,msg,p,caddr);}else if(msg.type==Chat){do_chat(sockfd,msg,p,caddr); }else if(msg.type==Quit){strcpy(msg.text,"以下线");printf("ip:%s pord:%d name:%s\n",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port),msg.name);printf("状态:%s\n",msg.text);do_quit(sockfd,msg,p,caddr); }}close(sockfd);return 0;
}
//登录的函数
//功能:
//1》将新登录的用户转发给所有已经登录的用户(遍历链表发送谁登录的消息)
//2》创建新节点来保存新登录用户的信息,链接到链表尾就可以
void do_login(int sockfd,msg_t msg,node_t *p,struct sockaddr_in caddr)
{sprintf(msg.text,"%s 以上线",msg.name);while(p->next != NULL){p= p->next;sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&(p->caddr),sizeof(p->caddr));//printf("%s\n",msg.text);}node_t *new=(node_t *)malloc(sizeof(node_t));//初始化new->caddr=caddr;new->next=NULL;//链接到链表尾p->next=new;return;
}
//群聊的函数
//功能:将客户端发来的聊天内容转发给所有已登录的用户,除了发送聊天内容的用户以外
void do_chat(int sockfd,msg_t msg,node_t *p,struct sockaddr_in caddr)
{//遍历链表while(p->next != NULL){p=p->next;if(memcmp(&(p->caddr),&caddr,sizeof(caddr)) != 0){sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&(p->caddr),sizeof(p->caddr));}}return;
}
//退出函数
//功能:
//1》将谁退出的消息转发给i所有用户
//2》将链表中保存这个推出的用户信息的节点删除
void do_quit(int sockfd,msg_t msg,node_t *p,struct sockaddr_in caddr)
{sprintf(msg.text,"%s 以下线",msg.name);while(p->next != NULL){if((memcmp(&(p->next->caddr),&caddr,sizeof(caddr)))==0){ node_t *dele=NULL;dele = p->next;p->next=dele->next;free(dele);dele=NULL;}else{p=p->next;sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&(p->caddr),sizeof(p->caddr));} }return;
}
client.c代码部分:
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<string.h>
#include<stdlib.h>
#include <sys/wait.h>
#include<dirent.h>
#include<sys/stat.h>enum type_t
{Login,Chat,Quit,
};
typedef struct
{char type;//L C Qchar name[32];//char text[128];//
}msg_t;int main(int argc, char const *argv[])
{if(argc !=3){printf("Usage ./a.out <ip> <port>\n");return -1;}int sockfd = socket(AF_INET,SOCK_DGRAM,0);if(sockfd<0){perror("socket err");exit(-1);}struct sockaddr_in serveraddr;serveraddr.sin_family=AF_INET;serveraddr.sin_port=htons(atoi(argv[2]));serveraddr.sin_addr.s_addr=inet_addr(argv[1]);socklen_t len = sizeof(serveraddr);msg_t msg;//先执行登录操作 printf("请登录:\n");msg.type=Login;printf("请输入用户名:");fgets(msg.name,32,stdin);if(msg.name[strlen(msg.name)-1]=='\n')msg.name[strlen(msg.name)-1]='\0';//发送登录消息if(sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&serveraddr,len)<0){perror("sendto err");exit(-1);}pid_t pid=fork();if(pid<0){perror("fork err");exit(-1);}else if(pid==0){while(1){if(recvfrom(sockfd,&msg,sizeof(msg),0,NULL,NULL)<0){perror("recvfrom err");return -1;}printf("[%s]:%s\n",msg.name,msg.text);} } else {while(1){fgets(msg.text,sizeof(msg.text),stdin);if(msg.text[strlen(msg.text)-1]=='\n')msg.text[strlen(msg.text)-1]='\0';if(strcmp(msg.text,"quit")==0){msg.type=Quit; sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&serveraddr,len);kill(pid,SIGKILL);wait(NULL);exit(-1);}else{msg.type=Chat;}//发送消息sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&serveraddr,len);}}close(sockfd);return 0;
}
相关文章:
网络聊天室
一、项目要求 利用UDP协议,实现一套聊天室软件。服务器端记录客户端的地址,客户端发送消息后,服务器群发给各个客户端软件。 问题思考 客户端会不会知道其它客户端地址? UDP客户端不会直接互连,所以不会获知其它客…...
ChatGPT只是玩具:生成式人工智能在不同行业的应用
源自:IT经理网 生成式人工智能的十一个行业用例 打开生成式 AI的正确姿势 声明:公众号转载的文章及图片出于非商业性的教育和科研目的供大家参考和探讨,并不意味着支持其观点或证实其内容的真实性。版权归原作者所有,如转载稿涉及版权等问题&…...
RestFul的风格是什么
RestFul的风格是什么? 当我们谈论RESTful风格时,它指的是一种设计和构建网络应用程序的原则和约定。以下是RESTful风格的一些主要特点: 资源:将应用程序的功能封装为资源,每个资源都有一个唯一的标识符(U…...
【自制C/C++小项目JuLongEditor】使用Windows控制台API来制作一个简单的文本编辑器
2023年8月22日,周二下午 昨天花了一个下午和晚上来制作的, 实现了一些基本的功能, 但由于代码只有130行,所以存在很多不足之处 GitHub:GitHub - JuLongZhiLu/JuLongEditor: C/C小项目,使用Windows控制台…...
中国芯,寻找新赛道迫在眉睫
北京华兴万邦管理咨询有限公司 商瑞 陈皓 近期国内半导体行业的热点可以用两个“有点多”来描述,一个是中国芯群体中上市公司股价闪崩的有点多,另一个是行业和企业的活动有点多。前者说明了许多国内芯片设计企业(fabless商业模式)…...
C++ 好用的格式化库--fmt
背景 fmt 库是一个开源的 C 格式化库,它提供了一种简洁、安全和高效的方式来进行字符串格式化。该库的设计目标是提供与 Python 的字符串格式化语法类似的功能,同时保持 C 的类型安全性和性能。 下载与安装 官网下载 fmt 官网地址:https:…...
微信小程序教学系列(3)
微信小程序教学系列 第三章:小程序高级开发技巧 1. 小程序API的使用 小程序API简介 小程序API是小程序提供的一系列接口,用于实现各种功能和操作。通过调用小程序API,可以实现页面跳转、数据存储、网络请求等功能。 使用小程序API的步骤…...
ORB-SLAM系列算法演进
ORB-SLAM算法是特征点法的代表,当前最新发展的ORB-SLAM3已经将相机模型抽象化,适用范围非常广,虽然ORB-SLAM在算法上的创新并不是很丰富,但是它在工程上的创新确实让人耳目一新,也能更好的为AR、机器人的算法实现落地。…...
solidity0.8.0的应用案例11:透明代理合约
选择器冲突 智能合约中,函数选择器(selector)是函数签名的哈希的前4个字节。例如mint(address account)的选择器为bytes4(keccak256("mint(address)")),也就是0x6a627842. 由于函数选择器仅有4个字节,范围很小,因此两个不同的函数可能会有相同的选择器,例如…...
最新消息:谷歌将在Chromebook上运用UWB技术,无线通信更上一层
超宽带(UWB)技术是一种创新的短距离无线通信技术,具有高速数据传输和精确定位物体位置的优势。尽管该技术已经存在一段时间,但最近开始广泛应用于各种设备中。据最新报道,Pixel Watch 2可能会搭载UWB模块,这…...
php+echarts实现数据可视化实例3
效果 全部代码 <?php include(includes/session.inc); include(includes/SQL_CommonFunctions.inc); ?> <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" …...
ubuntu下安装Sphinx,编译pdf
安装WSL2: 以管理员身份打开PowerShellwsl --install 来安装其他 Linux 发行版wsl --list --verbose 查看安装在 Windows 计算机上的 Linux 发行版列表 安装sphinx: sudo apt-get updatesudo apt-get install python3-sphinxsudo apt-get install lat…...
vue2.x项目从0到1(七)之用户权限
此章节偏理论知识 对于小一点的项目 比如说角色都是平级的 那我们直接像之前 vue2.x项目从0到1(二)之后台管理侧边栏(动态渲染路由以及高亮)_vue动态渲染侧边栏_关忆北_的博客-CSDN博客这样渲染就行了 但是一旦项目大了 …...
上传镜像到阿里云的ACR
1、开通阿里云ACR 2、在ACR 中创建命名空间 3、本地安装docker 4、登录到 开通ACR,需要配置访问凭证 [rootmaster ~]# docker login --username***lb registry.cn-beijing.aliyuncs.com Password: 5、给镜像打标签 [rootmaster ~]# docker images REPOSITORY …...
ahooks.js:一款强大的React Hooks库及其API使用教程(五)
一、ahooks.js简介二、ahooks.js安装三、继续ahooks.js API的介绍与使用教程61. useEventTarget62. useExternal63. useFavicon64. useMutationObserver65. useLongPress66. useScroll67. useResponsive68. useFocusWithin69. useControllableValue70. useEventEmitter 一、aho…...
MySQL TCL 事务控制
文章目录 1.事务四大特性2.事务并发问题3.事务隔离级别4.隔离级别查看与设置5.动提交事务5.1 查看自动提交事务5.2 关闭或开启自动提交事务 6.事务执行的基本流程7.设置事务的保存点参考文献 说到事务控制,先说一下数据库的事务是什么以及 MySQL 中我们必知的知识点…...
【Ubuntu】从Graylog到Grafana Loki:构建更强大的网络设备管理和监控系统
在将Graylog部署到生产环境时,我们遇到了一些问题,其中最主要的是无法安装MongoDB并且无法随时重启机器去修改BIOS设置来修复问题 【WARNING: MongoDB 5.0 requires a CPU with AVX support, and your current system does not appear to have that! 】。…...
[JavaWeb]【八】web后端开发-Mybatis
目录 一 介绍 二 Mybatis的入门 2.1 快速入门 2.1.1 准备SpringBoot工程 2.1.2 创建数据库mybatis以及对应库表user 2.1.3 创建User实体类 2.1.4 配置application.properties数据库连接信息 2.1.5 编写sql语句(注解方式) 2.1.6 测试运行 2.1.7 配…...
Flink源码之Checkpoint执行流程
Checkpoint完整流程如上图所示: JobMaster的CheckpointCoordinator向所有SourceTask发送RPC触发一次CheckPointSourceTask向下游广播CheckpointBarrierSouceTask完成状态快照后向JobMaster发送快照结果非SouceTask在Barrier对齐后完成状态快照向JobMaster发送快照结…...
【工具使用】Git的使用
dev代表开发版 1. git clone 命令 通过 git add <name> 对文件进行跟踪,把<name>加入到暂存区 git commit -m XXXXXXX 提交修改并补充XXXXX作为注释 “暂存”状态:出现了一些修改,但是还没有提交 对于Java来说,.cl…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
