5.26作业
服务器
2 3 #define BUFSIZE 10244 #define login_msg_len 205 6 typedef struct Node{7 char name[login_msg_len];8 struct sockaddr_in addr;9 struct Node *next;10 }Node;11 12 typedef struct Msgtype{13 char type;14 char username[login_msg_len];15 char content[BUFSIZE];16 }Msgtype;17 18 Node *create_node(in_port_t SER_PORT,const char * SER_IP_STR);19 Node *add_node(char *name,struct sockaddr_in addr);20 int print_msg(Msgtype *msg);21 void broadcast(int sfd,Node *head,Msgtype *msg);22 int is_exist(Node *head,Msgtype *msg);23 int is_empty(Node *head);24 void insert_node(Node *head,char *name,struct sockaddr_in addr);25 void delete_node(Node *head,char *name);26 void broadcast_system(int sfd,Node *head,char *input_buf);27 28 int main(int argc, char const *argv[])29 {30 if(3>argc){31 printf("输入格式不对,请按照以下格式输入:./server ip port\n");32 exit(1);33 }34 const char *SER_IP_STR=argv[1];35 in_port_t SER_PORT=atoi(argv[2]);36 37 int sfd=-1;38 if((sfd=socket(AF_INET,SOCK_DGRAM,0))<0){39 perror("socket");40 exit(1);41 }42 43 struct sockaddr_in addr;44 memset(&addr,0,sizeof(addr));45 addr.sin_family=AF_INET;46 addr.sin_port=htons(SER_PORT);47 if(inet_aton(SER_IP_STR,&addr.sin_addr)==0){48 perror("inet_aton");49 exit(1);50 }51 52 if(bind(sfd,(struct sockaddr*)&addr,sizeof(addr))<0){53 perror("bind");54 exit(1);55 }56 printf("bind success\n");57 Node *head=create_node(SER_PORT,SER_IP_STR);58 59 struct pollfd pfd[2];60 pfd[0].fd = sfd;61 pfd[0].events = POLLIN;62 pfd[1].fd = 0;63 pfd[1].events = POLLIN;64 65 struct sockaddr_in client_addr;66 socklen_t client_addr_len=sizeof(client_addr);67 68 Msgtype client_msg;69 memset(&client_msg,0,sizeof(client_msg));70 71 while(1){72 int ret=poll(pfd,2,-1);73 if(ret<0){74 perror("poll");75 exit(1);76 }else if (ret==0){77 printf("poll timeout\n");78 continue;79 }80 if(pfd[0].revents==POLLIN){81 int recv_len=recvfrom(sfd,&client_msg,sizeof(client_msg),0,(struct sockaddr*)&client_addr,&client_addr_l82 if(recv_len<0){83 perror("recvfrom");84 exit(1);85 }86 if(print_msg(&client_msg)==1){87 if(is_exist(head,&client_msg)){88 client_msg.type='E';89 sendto(sfd,&client_msg,sizeof(client_msg),0,(struct sockaddr*)&client_addr,sizeof(client_addr));90 continue;91 }else{92 insert_node(head,client_msg.username,client_addr);93 client_msg.type='L';94 strcpy(client_msg.content,"进入聊天室");95 broadcast(sfd,head,&client_msg);96 }97 }else if (print_msg(&client_msg)==2){98 printf("%s发送消息\n",client_msg.username);99 broadcast(sfd,head,&client_msg);
100 }else if (print_msg(&client_msg)==3){
101 delete_node(head,client_msg.username);
102 client_msg.type='Q';
103 strcpy(client_msg.content,"退出聊天室");
104 broadcast(sfd,head,&client_msg);
105 }else{
106 char *msg="消息类型错误";
107 for(int i=0;i<sizeof(msg);i++){
108 client_msg.content[i]=msg[i];
109 }
110 sendto(sfd,&client_msg,sizeof(client_msg),0,(struct sockaddr*)&client_addr,sizeof(client_msg));
111 continue;
112 }
113 }
114 if(pfd[1].revents==POLLIN){
115 char input_buf[BUFSIZE];
116 fgets(input_buf,BUFSIZE,stdin);
117 input_buf[strlen(input_buf)-1]='\0';
118 if(is_empty(head)){
119 printf("聊天室为空,请等待其他用户登录\n");
120 continue;
121 }
122 broadcast_system(sfd,head,input_buf);
123 }
124 }
125 close(sfd);
126 return 0;
127 }
128 Node *create_node(in_port_t SER_PORT,const char * SER_IP_STR){
129 Node *node=(Node*)malloc(sizeof(Node));
130 if(node==NULL){
131 perror("malloc");
132 exit(1);
133 }
134 char *msg="system";
135 for(int i=0;i<sizeof(msg);i++){
136 node->name[i]=msg[i];
137 }
138 node->addr.sin_family=AF_INET;
139 node->addr.sin_port=htons(SER_PORT);
140 node->addr.sin_addr.s_addr=inet_addr(SER_IP_STR);
141 node->next=NULL;
142 return node;
143 }
144 Node *add_node(char *name,struct sockaddr_in addr){
145 Node *new_node=(Node*)malloc(sizeof(Node));
146 if(new_node==NULL){
147 perror("malloc");
148 exit(1);
149 }
150 strcpy(new_node->name,name);
151 new_node->addr=addr;
152 new_node->next=NULL;
153 return new_node;
154 }
155 int is_empty(Node *head){
156 if(head==NULL){
157 return 1;
158 }
159 return head->next==NULL?1:0;
160 }
161 void insert_node(Node *head,char *name,struct sockaddr_in addr){
162 if(head==NULL){
163 perror("head is null");
164 exit(1);
165 }
166 Node *new_node=add_node(name,addr);
167 new_node->next=head->next;
168 head->next=new_node;
169 printf("%s进入聊天室\n",name);
170 }
171 int print_msg(Msgtype *msg){
172 switch(msg->type){
173 case 'L':
174 return 1;
175 case 'C':
176 return 2;
177 case 'Q':
178 return 3;
179 default:
180 return 0;
181 }
182 }
183 int is_exist(Node *head,Msgtype *msg){
184 if(head==NULL){
185 perror("head is null");
186 exit(1);
187 }
188 if(is_empty(head)){
189 return 0;
190 }
191 Node *p=head->next;
192 while(p!=NULL){
193 if(strcmp(p->name,msg->username)==0){
194 return 1;
195 }
196 p=p->next;
197 }
198 return 0;
199 }
200 void broadcast(int sfd,Node *head,Msgtype *msg){
201 if(head==NULL){
202 perror("head is null");
203 exit(1);
204 }
205 if(is_empty(head)){
206 printf("聊天室为空\n");
207 return;
208 }
209 Node *p=head->next;
210 while(p!=NULL){
211 if(strcmp(p->name,msg->username)!=0){
212 sendto(sfd,msg,sizeof(Msgtype),0,(struct sockaddr*)&p->addr,sizeof(p->addr));
213 }
214 p=p->next;
215
216 }
217 }
218 void delete_node(Node *head,char *name){
219 if(head==NULL){
220 perror("head is null");
221 exit(1);
222 }
223 if(is_empty(head)){
224 printf("聊天室为空\n");
225 return;
226 }
227 printf("%s退出聊天室\n",name);
228 Node *p=head->next;
229 Node *pre=head;
230 while(p!=NULL){
231 if(strcmp(p->name,name)==0){
232 pre->next=p->next;
233 free(p);
234 return;
235 }
236 pre=p;
237 p=p->next;
238 }
239
240 }
241 void broadcast_system(int sfd,Node *head,char *content){
242 if(head==NULL){
243 perror("head is null");
244 exit(1);
245 }
246 if(is_empty(head)){
247 printf("聊天室为空\n");
248 return;
249 }
250 Msgtype msg;
251 msg.type='C';
252 strcpy(msg.username,"system");
253 strcpy(msg.content,content);
254 Node *p=head->next;
255 while(p!=NULL){
256 sendto(sfd,&msg,sizeof(Msgtype),0,(struct sockaddr*)&p->addr,sizeof(p->addr));
257 p=p->next;
258 }
259 printf("system发送消息:%s\n",content);
260 }
~
~
客户端
#include <header.h>#define BUFSIZE 1024#define login_msg_len 20 typedef struct Msgtype{char type;char username[login_msg_len];char content[BUFSIZE];}Msgtype;int main(int argc, char const *argv[]){if(3>argc){ printf("输入格式不对,请按照以下格式输入:./server ip port\n");}const char *SER_IP_STR=argv[1];int SER_PORT=atoi(argv[2]);int sfd=-1;if((sfd=socket(AF_INET,SOCK_DGRAM,0))<0){perror("socket");exit(1);}struct sockaddr_in server_addr;memset(&server_addr,0,sizeof(server_addr));server_addr.sin_family=AF_INET;server_addr.sin_port=htons(SER_PORT);if(inet_aton(SER_IP_STR,&server_addr.sin_addr)==0){perror("inet_aton");exit(1);}socklen_t addr_len=sizeof(server_addr);Msgtype recv_msg;memset(&recv_msg,0,sizeof(recv_msg));Msgtype send_msg;memset(&send_msg,0,sizeof(send_msg));Msgtype login_msg;while (1){memset(&login_msg,0,sizeof(login_msg));login_msg.type='L';printf("请输入用户名:");fgets(login_msg.username, login_msg_len, stdin);login_msg.username[strcspn(login_msg.username, "\n")] = '\0'; if (sendto(sfd, &login_msg, sizeof(login_msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0){perror("sendto");exit(1);}struct pollfd pfd[2];pfd[0].fd = sfd; pfd[0].events = POLLIN; pfd[1].fd = 0; pfd[1].events = POLLIN; while(1){int ret=poll(pfd,2,-1);if(ret<0){perror("poll");exit(1);}else if (ret==0){printf("poll timeout\n");continue;}if(pfd[0].revents==POLLIN){int len=recvfrom(sfd, &recv_msg, sizeof(recv_msg), 0, (struct sockaddr *)&server_addr, &addr_len);if(len<0){perror("recvfrom");exit(1);}if(recv_msg.type=='L'){printf("-----------%s加入聊天室----------\n",recv_msg.username);}else if(recv_msg.type=='C'){printf("%s:%s\n",recv_msg.username,recv_msg.content);}else if (recv_msg.type=='Q') {printf("------------%s%s---------------\n",recv_msg.username,recv_msg.content);}else{printf("%s用户名已存在或服务器故障,请重新登录\n",login_msg.username);break;}}if(pfd[1].revents==POLLIN){char input[BUFSIZE];fgets(input,BUFSIZE, stdin);input[strcspn(input, "\n")] = '\0'; if(strcmp(input,"quit")==0){send_msg.type='Q';sendto(sfd, &send_msg, sizeof(send_msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));break;//退出循环}else{memset(&send_msg,0,sizeof(send_msg));send_msg.type='C';strncpy(send_msg.username,login_msg.username,login_msg_len);strncpy(send_msg.content,input,BUFSIZE);sendto(sfd, &send_msg, sizeof(send_msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));}}}}close(sfd);return 0;}
相关文章:
5.26作业
服务器 2 3 #define BUFSIZE 10244 #define login_msg_len 205 6 typedef struct Node{7 char name[login_msg_len];8 struct sockaddr_in addr;9 struct Node *next;10 }Node;11 12 typedef struct Msgtype{13 char type;14 char username[login_msg_len]…...
链接库文件体积优化工具篇:bloaty
笔者之前参与过一个嵌入式智能手表项目,曾经碰到过这样一个问题:手表的flash大小只有2M,这意味着只能在上面烧录2M大小的代码。随着开发不断进行,代码越写越多,编译出来的bin也越来越大。最后bin大小超过了2M, 就没法烧…...
使用pyqt绘制一个爱心!
使用pyqt绘制一个爱心! 介绍效果代码 介绍 使用pyqt绘制一个爱心! 效果 代码 import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget from PyQt5.QtGui import QPainter, QPen, QBrush, QColor from PyQt5.QtCore import Qt, Q…...
关于 Transformer 的11个常见面试题
Transformer 是如何工作的? Transformer 是一种深度学习算法,特别适用于自然语言处理(NLP)任务,如语言翻译、语言生成和语言理解。它们能够处理长度可变的输入序列并捕捉长距离依赖关系,使其在理解和处理自…...
OS多核多线程锁记录笔记
自旋锁作用 自旋锁的是为了保护两个核上的公共资源,也就是全局变量,只有在一方也就是一个核抢到了自选锁,才能对公共资源进行操作修改,当然还有其他形似的锁如互斥锁,这里不比较两者的区别,以前没有深入的去…...
nginx做TCP代理
要实现TCP代理,可以使用Nginx的stream模块。stream模块允许Nginx作为一个转发代理来处理TCP流量,包括TCP代理、负载均衡和SSL终止等功能。 以下是配置Nginx实现TCP代理的基本步骤: 在Nginx配置文件中添加stream块,并在该块中配置…...
python 异常处理 try
异常 我们常见的代码错误后 会出现此类异常 SyntaxError:语法错误 AttributeError:属性错误 IndexError:索引错误 TypeError:类型错误 NameError:变量名不存在错误 KeyError:映射中不存在的关键字…...
月入10万+管道收益,揭秘旅游卡运营的5个阶段!
网上的项目众多,只要用心,便能发现不少商机。在互联网上运营,关键在于理解项目的底层逻辑。今天,我们来揭秘旅游卡项目,如何做到月入10万。 1、先赚成本 开始项目时,首要任务是回本。不要急于求成&#x…...
android_binder源码分析之_binder驱动使用服务
一,binder驱动源码分析,使用服务过程 uint32_t svcmgr_lookup(struct binder_state *bs, uint32_t target, const char *name) {uint32_t handle;unsigned iodata[512/4];struct binder_io msg, reply;bio_init(&msg, iodata, sizeof(iodata), 4);b…...
【波点音乐看广告】
import uiautomator2 as u2 import time from datetime import datetime import xml.etree.ElementTree as ET import re import os 连接设备 d u2.connect() os.system(‘adb shell chmod 775 /data/local/tmp/atx-agent’) os.system(‘adb shell /data/local/tmp/atx-age…...
[SWPUCTF 2021 新生赛]pop
常见的魔术方法 魔术方法__construct() 类的构造函数,在对象实例化时调用 __destruct() 类的析构函数,在对象被销毁时被调用 __call() 在对象中调用一个不可访问的对象时被调用,比如一个对象被调用时,里面没有程序想调用的属性 …...
【DevOps】Jenkins + Dockerfile自动部署Maven(SpringBoot)项目
环境 docker_host192.168.0.1jenkins_host192.168.0.2 jenkins_host构建完成后把jar发布到docker_host,再通过dockerfile自动构建镜像,运行镜像 1 Jenkins安装 AWS EC2安装Jenkins:AWS EC2 JDK11 Jenkins-CSDN博客 AWS EC2上Docker安装…...
【C++】——入门基础知识超详解
目录 编辑 1.C关键字 2. 命名空间 2.1 命名空间定义 2.2 命名空间使用 命名空间的使用有三种方式: 注意事项 3. C输入&输出 示例 1:基本输入输出 示例 2:读取多个值 示例 3:处理字符串输入 示例 4:读…...
ChatGPT技术演进简介
chatGPT(chat generative pre-train transformer, 可以对话的预训练trasformer模型),讨论点: 1、chatGPT为什么突然火了 2、GPT 1.0、2.0、3.0、3.5 、4和4o区别和特性,在不同应用场景中如何选对模型 3、未…...
C语言 | Leetcode C语言题解之第114题二叉树展开为链表
题目: 题解: void flatten(struct TreeNode* root) {struct TreeNode* curr root;while (curr ! NULL) {if (curr->left ! NULL) {struct TreeNode* next curr->left;struct TreeNode* predecessor next;while (predecessor->right ! NULL)…...
Vue 子组件向父组件传值
1、使用自定义事件 ($emit) 这是Vue中最常用的子组件向父组件传递数据的方式。子组件通过触发一个自定义事件,并附加数据作为参数,父组件则监听这个事件并处理传递过来的数据。 子组件 (发送数据): <template><button click"…...
【前端笔记】Vue项目报错Error: Cannot find module ‘webpack/lib/RuleSet‘
网上搜了下发现原因不止一种,这里仅记录本人遇到的原因和解决办法,仅供参考 原因:因为某种原因导致本地package.json中vue/cli与全局vue/cli版本不同导致冲突。再次提示,这是本人遇到的,可能和大家有所不同,…...
edge浏览器的网页复制
一些网页往往禁止复制粘贴,本文方法如下: 网址最前面加上 read: (此方法适用于Microsoft Edge 浏览器)在此网站网址前加上read:进入阅读器模式即可...
视频播放器-Kodi
一、前言 Kodi 是一款开源免费的多媒体播放软件。Kodi 是由非营利性技术联盟 Kodi 基金会开发的免费开源媒体播放器应用程序。 Kodi是一款免费和开源(遵循GPL协议)的多媒体播放器和娱乐中心软件,由XBMC基金会开发。Kodi的主要功能是管理和播…...
Helm安装kafka3.7.0无持久化(KRaft 模式集群)
文章目录 2.1 Chart包方式安装kafka集群 5.开始安装2.2 命令行方式安装kafka集群 搭建 Kafka-UI三、kafka集群测试3.1 方式一3.2 方式二 四、kafka集群扩容4.1 方式一4.2 方式二 五、kafka集群删除 参考文档 [Helm实践---安装kafka集群 - 知乎 (zhihu.com)](https://zhuanlan.…...
RK3568平台开发系列讲解:注册 platform 驱动过程详解
🚀返回专栏总目录 文章目录 一、注册 platform 驱动 二、probe函数 三、platform_driver 结构体 一、注册 platform 驱动 platform_driver_register 函数用于在 Linux 内核中注册一个平台驱动程序。 下面是对该函数的详细介绍: 该函数在内核源码目录下的“/include/linux/p…...
Java核心技术 卷1 基础知识 原书第10版--中文版扫描--带书签已OCR.pdf分享
Java核心技术 卷1 基础知识 原书第10版–中文版扫描–带书签已OCR 下载链接 百度网盘下载 链接:https://pan.baidu.com/s/17CJ-96c9XCcry0yZbaqxrg?pwdnu8v 提取码:nu8v 复制这段内容后打开百度网盘手机App,操作更方便哦 资源介绍 文件名: Java核心技术 卷1 基…...
告别复制粘贴!用Vue CLI插件一键集成Cesium到Vue2老项目
告别复制粘贴!用Vue CLI插件一键集成Cesium到Vue2老项目 在Vue2项目中引入Cesium进行3D地理可视化开发时,传统的手动集成方式往往需要处理复杂的Webpack配置、静态资源管理和全局变量注入。这种"复制粘贴"式的集成不仅效率低下,还容…...
UI For Docker完整贡献指南:10个步骤成为开源社区达人
UI For Docker完整贡献指南:10个步骤成为开源社区达人 【免费下载链接】ui-for-docker A web interface for Docker, formerly known as DockerUI. This repo is not maintained 项目地址: https://gitcode.com/gh_mirrors/ui/ui-for-docker UI For Docker是…...
如何实现Karmada多集群编排:API Server与Controller Manager的终极协同架构指南
如何实现Karmada多集群编排:API Server与Controller Manager的终极协同架构指南 【免费下载链接】karmada Open, Multi-Cloud, Multi-Cluster Kubernetes Orchestration 项目地址: https://gitcode.com/GitHub_Trending/ka/karmada Karmada作为一款开源的多集…...
CTF小白也能懂:手把手教你用BurpSuite爆破HTTP基础认证靶场(附Python脚本)
CTF从零到一:BurpSuite破解HTTP基础认证全流程实战 第一次接触CTF比赛时,看到那些复杂的Web安全挑战总让人望而生畏。记得我最早遇到HTTP基础认证这道关卡时,盯着浏览器弹出的登录窗口整整发呆了半小时——明明知道密码就在字典文件里&#x…...
5步焕新Win11桌面:MicaForEveryone打造个性化窗口美学指南
5步焕新Win11桌面:MicaForEveryone打造个性化窗口美学指南 【免费下载链接】MicaForEveryone Mica For Everyone is a tool to enable backdrop effects on the title bars of Win32 apps on Windows 11. 项目地址: https://gitcode.com/gh_mirrors/mi/MicaForEve…...
多模态开发工具:LangChain与LlamaIndex——赋能软件测试的新引擎
测试领域的智能化变革在人工智能浪潮席卷各行各业的当下,软件测试作为保障软件质量的关键环节,正经历着深刻的智能化转型。传统的测试方法依赖大量人工编写用例、执行回归、分析结果,不仅效率受限,在面对日益复杂的系统架构和海量…...
AI设计新利器!我外卖都没到,你方案图就出来了!
凌晨两点,设计部灯火通明。 小王盯着屏幕上改了第18版的方案,揉了揉酸涩的眼睛。甲方上午刚推翻上周确定的概念,明天就要看新方案。市场部的同事在旁边催:“客户说再不出图就要换供应商了。”而结构组的同事还在等着方案定稿才能…...
SEO 查看哪些页面最重要
SEO查看哪些页面最重要:深度解析与实用建议 在当今数字营销的世界中,搜索引擎优化(SEO)无疑是每个网站运营者都必须关注的关键环节。为了提升网站在搜索引擎结果中的排名,了解哪些页面对SEO最重要是至关重要的。本文将…...
