UDP网络聊天室(更)

服务器端

#include <header.h>
typedef struct node
{char name[20];struct sockaddr_in cli_addr;struct node *next;
}node,*node_p;
typedef struct msg
{char type;char name[20];char text[128];
}msg;
node_p create_link()
{node_p H=(node_p)malloc(sizeof(node));if(H==NULL){printf("apply fail\n");return NULL;}H->next=NULL;return H;
}
node_p create_node(char *name,struct sockaddr_in cli_addr)
{node_p new=(node_p)malloc(sizeof(node));if(new==NULL){printf("apply fail\n");return NULL;}strcpy(new->name,name);new->cli_addr=cli_addr;new->next=NULL;return new;
}
void insert(node_p H,char *name,struct sockaddr_in cli_addr)
{if(H==NULL){printf("apply fail\n");return;}node_p new=create_node(name,cli_addr);new->next=H->next;H->next=new;
}
void delete(node_p H,char* name)
{if(H==NULL){printf("apply fail\n");return;}node_p p=H->next;while(p!=NULL&&strcmp(p->next->name,name)!=0){p=p->next;}node_p p1=p->next;p->next=p->next->next;free(p1);
}
int main(int argc, const char *argv[])
{if(argc!=3){printf("请依次输入正确的ip地址和端口号!\n");return 1;}const char *SER_IP=argv[1];int SER_PORT=atoi(argv[2]);int sfd=socket(AF_INET,SOCK_DGRAM,0);               if(sfd==-1){perror("socket");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");return 1;}struct sockaddr_in cin;socklen_t addrlen=sizeof(cin);char wbuf[128]={0};struct pollfd pfd[2];pfd[0].fd=sfd;pfd[1].fd=0;pfd[0].events=POLLIN;pfd[1].events=POLLIN;node_p H=create_link();msg msg;printf("等待用户加入....\n");while(1){int res=poll(pfd,2,-1);if(res==-1){perror("poll");return 1;}else if(res==0){printf("time out\n");return 1;}if(pfd[0].revents==POLLIN){memset(&msg,0,sizeof(msg));recvfrom(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&cin,&addrlen);if(msg.type=='n'){node_p p=H->next;insert(H,msg.name,cin);printf("*********\033[1;35m[%s\033[0m:\033[1;32m%d] \033[33m %s\033[0m\033[1;36m 已进入聊天室\033[0m*********** \n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),msg.name);while(p!=NULL){sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->cli_addr,sizeof(p->cli_addr));p=p->next;}}else if(msg.type=='t'){node_p p=H->next;printf("%s:%s\n",msg.name,msg.text);while(p!=NULL){msg.type='t';if(strcmp(p->name,msg.name)!=0){sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->cli_addr,sizeof(p->cli_addr));}p=p->next;}}else if(msg.type=='q'){printf("\033[1;36m%s离开了聊天室...\n",msg.name);node_p p=H->next;while(p!=NULL){msg.type='q';sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->cli_addr,sizeof(p->cli_addr));p=p->next;}}}if(pfd[1].revents==POLLIN){msg.type='s';bzero(wbuf,sizeof(wbuf));fgets(wbuf,sizeof(wbuf),stdin);strcpy(msg.text,wbuf);msg.text[strlen(msg.text)-1]=0;node_p p=H->next;while(p!=NULL){msg.type='s';sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->cli_addr,sizeof(p->cli_addr));p=p->next;}printf("\033[1;36m系统消息推送成功。\n");}}close(sfd);return 0;
}

客户端

#include <header.h>
int quit_flag=0;
typedef struct msg
{char type;char name[20];char text[128];
}msg;
int main(int argc, const char *argv[])
{if(argc!=3){printf("\033[1;35m请依次输入正确的ip地址和端口号!\n");return 1;}const char *SER_IP=argv[1];int SER_PORT=atoi(argv[2]);printf("\033[1;36m请输入用户名:");int cfd=socket(AF_INET,SOCK_DGRAM,0);if(cfd==-1){perror("socket");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 addrlen=sizeof(sin);struct pollfd pfd[2];   pfd[0].fd=0;pfd[1].fd=cfd;pfd[0].events=POLLIN;pfd[1].events=POLLIN;msg msg;char username[20]={0};fgets(username,sizeof(username),stdin);strcpy(msg.name,username);msg.name[strlen(msg.name)-1]=0;msg.type='n';sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));char rbuf[128]={0};while(1){int res=poll(pfd,2,-1);if(res==-1){perror("poll");return 1;}else if(res==0){printf("time out\n");return 1;}if(pfd[0].revents==POLLIN){msg.type='t';strcpy(msg.name,username);msg.name[strlen(msg.name)-1]=0;char txt[128]={0};bzero(txt,sizeof(txt));fgets(txt,sizeof(txt),stdin);strcpy(msg.text,txt);msg.text[strlen(msg.text)-1]=0;int flag=0;if(strcmp(msg.text,"quit")==0){msg.type='q';sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));flag=1;quit_flag=1;}if(flag==0){sendto(cfd,&msg,sizeof(msg),MSG_DONTWAIT,(struct sockaddr*)&sin,sizeof(sin));}}if(pfd[1].revents==POLLIN){recvfrom(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,&addrlen);if(msg.type=='t'){printf("\033[1;34m%s:\033[0m%s\n",msg.name,msg.text);}else if(msg.type=='n'){printf("-----------------\033[1;33m %s \033[1;35m 已上线 \033[1;33m--------------\n",msg.name);}else if(msg.type=='s'){printf("\033[1;36msystem:%s\n",msg.text);}else if(msg.type=='q'){printf("-----------------\033[1;33m %s\033[1;35m  已下线 \033[1;33m-------------\n",msg.name);if(quit_flag==1){break;}}}}close(cfd);exit(0);return 0;
}

功能实现

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

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

相关文章

C++ 数据类型

一 数据类型 数学中的数据类别 不同的性质&#xff1b; 不同的运算&#xff1b; 计算机中的数据类型 不同的表示形式 不同的存储空间 不同的运算 1 整数 注意 关于不同类型的数所占的字节数 C 没有规定不同类型的数占的字节数会因计算机系统、编译器的不同而不同sizeof()运算…

Trie字符串统计-java

Trie&#xff0c;又称前缀树或字典树&#xff0c;是一种有序树&#xff0c;用于保存关联数组&#xff0c;其中的键通常是字符串。 目录 前言☀ 一、Trie字符串统计☀ 二、算法思路☀ 1.Trie树定义&#x1f319; 2.变量解释&#x1f319; 3.插入操作&#x1f319; 4.Trie树查找操…

【算法】位运算算法——丢失的数字

题解&#xff1a;丢失的数字(位运算算法) 目录 1.题目2.题解3.位运算异或4.总结 1.题目 题目链接&#xff1a;LINK 2.题解 哈希数组查漏高斯求和排序位运算异或… 3.位运算异或 class Solution { public:int missingNumber(vector<int>& nums) {int ret 0;for…

动态规划之买卖股票大集合

目录 引言 1.只能进行一次买卖股票&#xff08;最多只能买一股股票&#xff09; 2.可以进行多次股票买卖&#xff0c;且没有手续费&#xff08;最多只能买一股股票&#xff09; 3.可以进行多次股票买卖&#xff0c;但是有冷冻期&#xff0c;无手续费&#xff08;最多只能买一…

电脑卡顿---WINDOWS任何关闭应用开机自启动

打开windows11的控制面板&#xff0c;点击应用&#xff0c;点击启动 如下图圈出来的地方就是开机自启动的开关按键。

Android 11 Audio音频系统配置文件解析

在AudioPolicyService的启动过程中&#xff0c;会去创建AudioPolicyManager对象&#xff0c;进而去解析配置文件 //frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientIn…

如何在生产环境中以非 Root 用户启动 Kafka

目录 如何在生产环境中以非 Root 用户启动 Kafka1. 创建 Kafka 用户2. 设置目录权限3. 配置 systemd 服务文件4. 启动和启用 Kafka 服务5. 验证 Kafka 服务经验总结 为了在生产环境中以非 root 用户&#xff08;如 kafka 用户&#xff09;启动 Kafka&#xff0c;您需要确保 Ka…

【软件测试】bug篇|软件测试的生命周期|描述bug的要素|bug的级别|bug的生命周期|高频面试题:与开发产⽣争执怎么处理

目录 一、软件测试的⽣命周期 二、BUG 2.1 bug的概念 2.2 描述bug的要素 2.3 bug级别 2.4 bug的⽣命周期 &#x1f4a1;2.5 与开发产⽣争执怎么办&#xff08;⾼频考题&#xff09; &#x1f4a1; 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&…

Unity实现首行缩进两个字符

效果 在Unity中如果想实现首行缩进两个字符&#xff0c;你会发现按空格是没法实现的。 实现原理&#xff1a;用空白的透明的字替代原来的位置。 代码&#xff1a; <color#FFFFFF00>XXX</color> 赶紧去试试吧&#xff01;

CASS11自定义宗地图框

1、找到CASS11的安装路径&#xff0c;找到如下文件夹&#xff1a; 2、打开【report】文件夹&#xff0c;如下&#xff1a; 3、打开其中一个压缩包&#xff0c;如【标准宗地图】压缩包&#xff0c;结果如下&#xff1a; 4、打开后&#xff0c;将其另存为到桌面&#xff0c;随后关…

新书推荐:7.5 goto、break、continue语句

本节必须掌握的知识点&#xff1a; 示例二十六 代码分析 汇编解析 示例二十七 代码分析 汇编解析 7.5.1 示例二十六 ■goto语句&#xff1a;无条件转移语句。 语法格式&#xff1a; goto label; label : 代码; ●语法解析&#xff1a; 执行到goto语句时&#xff0c;则无…

释放 OSINT 的力量:在线调查综合指南

开源情报 (OSINT) 是从公开信息中提取有价值见解的艺术。无论您是网络安全专业人士、道德黑客还是情报分析师&#xff0c;OSINT 都能为您提供先进的技术&#xff0c;帮助您筛选海量的数字数据&#xff0c;发现隐藏的真相。 在本文中&#xff0c;我们将深入研究大量的OSINT 资源…

项目十三:搜狗——python爬虫实战案例

根据文章项目十二&#xff1a;简单的python基础爬虫训练-CSDN博客的简单应用&#xff0c;这一次来升级我们的技术&#xff0c;那么继续往下看&#xff0c;希望对技术有好运。 还是老样子&#xff0c;按流程走&#xff0c;一条龙服务&#xff0c;嘿嘿。 第一步&#xff1a;导入…

12.2 通道-阻塞与流程控制、通道型函数、退出通道

阻塞与流程控制 通常在并发程序中要尽力避免阻塞式操作&#xff0c;但有时又需要让代码暂时处于阻塞状态&#xff0c;以等待某种条件、信号或数据&#xff0c;然后再继续运行。 对于无缓冲通道&#xff0c;试图从无人写入的通道中读取&#xff0c;或者向无人读取的通道中写入…

【Sql Server】随机查询一条表记录,并重重温回顾下自定义函数的封装和使用

大家好&#xff0c;我是全栈小5&#xff0c;欢迎来到《小5讲堂》。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 前言随机查询语…

MongoDB数据库(10亿条数据)清理策略: 自动化过期数据删除实战

1、引言 随着应用程序和业务数据的持续增长&#xff0c;有效地管理数据库存储空间成为维护系统性能的关键。在MongoDB这类NoSQL数据库中&#xff0c;定期清理过期数据变得尤为重要&#xff0c;这不仅能释放宝贵的存储资源&#xff0c;还能优化查询性能&#xff0c;确保数据库运…

5,串口编程---实现简单的用串口发送接收数据

单片机通过串口向PC机发送数据 PC机通过串口接收单片机发过来的数据 1.UART和USART的区别&#xff1a; USART支持同步通信方式,可以通过外部时钟信号进行同步传输,而UART仅支持异步通信方式 本开发板STM32F103ZET6有5个串口&#xff0c;用串口1作调试串口&#xff0c;因为串…

让AI学相机对焦: Learning to AutoFocus

前言 分析来自谷歌发表在 CVPR 2020 上的论文 Learning to Autofocus &#xff1a;https://arxiv.org/pdf/2004.12260 目前网上对这篇论文的分析较少&#xff0c;有的分析并没有指出关键点&#xff0c;如&#xff1a;论文解读&#xff1a; Learning to AutoFocus-CSDN博客&am…

spring常用知识点

1、拦截器和过滤器区别 1. 原理不同&#xff1a; 拦截器是基于java的反射机制&#xff0c;而过滤器采用责任链模式是基于函数回调的。 2. 使用范围不同&#xff1a; 过滤器Filter的使用依赖于Tomcat等容器&#xff0c;导致它只能在web程序中使用 拦截器是一个Sping组件&am…

jQuery 常用API

一、jQuery 选择器 1、jQuery 基础选择器 原生JS获取元素方式很多&#xff0c;很杂&#xff0c;而且兼容性情况不一致&#xff0c;因此jQuery给我们做了封装&#xff0c;使获取元素统一标准 2、jQuery 层级选择器 3、隐式迭代 遍历内部 DOM 元素&#xff08;伪数组形式存储&am…