当前位置: 首页 > news >正文

UDP聊天室

服务器端

#include <myhead.h>#define SER_IP "192.168.124.38"
#define SER_PORT 8888
#define RBUFSIZE 128
#define WBUFSIZE 128typedef struct node{char usrName[20];struct sockaddr_in cli_sockaddr;struct node* next;
}node, *node_p;node_p create_head_node();
node_p create_node(char* usrName, struct sockaddr_in cli_sockaddr);
void insert_tail(node_p H, char* usrName, struct sockaddr_in cli_sockaddr);
char* find(node_p H, struct sockaddr_in cli_sockaddr);
void delete(node_p H, struct sockaddr_in cli_sockaddr);int main(int argc, const char *argv[]){int sockfd;struct sockaddr_in ser_sockaddr;struct sockaddr_in cli_sockaddr;char wbuf[WBUFSIZE]={0};char rbuf[RBUFSIZE]={0};socklen_t addrlen = sizeof(struct sockaddr);struct pollfd pfds[2];// 创建头结点node_p H = create_head_node();sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd == -1){perror("socket");return -1;}ser_sockaddr.sin_family = AF_INET;ser_sockaddr.sin_port = htons(SER_PORT);ser_sockaddr.sin_addr.s_addr = inet_addr(SER_IP);if(bind(sockfd, (struct sockaddr*)&ser_sockaddr, sizeof(struct sockaddr)) == -1){perror("bind");return -1;}pfds[0].fd = 0;pfds[0].events = POLLIN;pfds[1].fd = sockfd;pfds[1].events = POLLIN;puts("Waiting for client connection...");//开始通信while (1) {poll(pfds, 2, -1);// 接受客户端发送的消息,并转发给其他客户端if (pfds[1].revents == POLLIN) {memset(rbuf, 0, sizeof(rbuf));recvfrom(sockfd, rbuf, RBUFSIZE, 0, (struct sockaddr*)&cli_sockaddr, &addrlen);// 判断客户端是否在链表内,即客户端是否已经连接char* ret = find(H, cli_sockaddr);// 用户未存在于链表中if (ret == NULL) {// 在客户端首次连接时,利用链表尾插存储客户端的用户名和地址信息insert_tail(H, rbuf, cli_sockaddr);// 服务器端输出客户端加入消息printf("%s [%s:%d] 加入聊天室\n", rbuf, inet_ntoa(cli_sockaddr.sin_addr), ntohs(cli_sockaddr.sin_port));// 将客户端上线的消息,发送给出了除了刚刚加入的客户端的所有主机node_p temp = H->next;//格式化客户端登录的消息char str[1024]={0};sprintf(str, "----%s加入聊天室----", rbuf);while (temp->next != NULL) {if (sendto(sockfd, str, strlen(str), 0, (struct sockaddr*)&temp->cli_sockaddr, sizeof(struct sockaddr)) == -1) {perror("sendto");}temp = temp->next;}}// 用户存在于链表中else if (ret > 0) {// 已登录客户端发送了退出信号,通知服务器以及其他所有用户if(strcmp(rbuf, "quit") == 0){// 格式化客户端退出消息char str[1024]={0};sprintf(str, "----%s退出聊天室----", ret);// 服务器端输出客户端退出消息printf("%s [%s:%d] 退出聊天室\n", ret, inet_ntoa(cli_sockaddr.sin_addr), ntohs(cli_sockaddr.sin_port));// 通知其他人node_p temp = H->next;while (temp != NULL) {if (sendto(sockfd, str, strlen(str), 0, (struct sockaddr*)&temp->cli_sockaddr, sizeof(struct sockaddr)) == -1) {perror("sendto");}temp = temp->next;}// 将退出的客户端从链表中删除delete(H, cli_sockaddr);}else{// 将客户端发送的消息转发给所有人(除了发送消息的客户端)// 格式化用户发送的消息char str[1024]={0};sprintf(str, "%s: %s", ret, rbuf);node_p temp = H->next;while (temp != NULL) {if (temp->cli_sockaddr.sin_addr.s_addr == cli_sockaddr.sin_addr.s_addr && temp->cli_sockaddr.sin_port == cli_sockaddr.sin_port){temp = temp->next;continue;}if (sendto(sockfd, str, strlen(str), 0, (struct sockaddr*)&temp->cli_sockaddr, sizeof(struct sockaddr)) == -1) {perror("sendto");}temp = temp->next;}printf("%s [%s:%d] 发送了一条消息\n", ret, inet_ntoa(cli_sockaddr.sin_addr), ntohs(cli_sockaddr.sin_port));}}}// 服务器向所有客户端发送消息if (pfds[0].revents == POLLIN) {memset(wbuf, 0, sizeof(wbuf));fgets(wbuf, sizeof(wbuf), stdin);wbuf[strlen(wbuf)-1] = 0;// 格式化服务器发送的消息char str[1024]={0};sprintf(str, "server: %s", wbuf);node_p temp = H->next;while (temp != NULL) {if (sendto(sockfd, str, strlen(str), 0, (struct sockaddr*)&temp->cli_sockaddr, sizeof(struct sockaddr)) == -1) {perror("sendto");}temp = temp->next;}printf("服务器 [%s:%d] 发送了一条消息\n",inet_ntoa(ser_sockaddr.sin_addr), ntohs(ser_sockaddr.sin_port));}}//关闭socketclose(sockfd);return 0;
}node_p create_head_node(){                                    node_p H=(node_p)malloc(sizeof(node));if(H==NULL){printf("空间申请失败\n");return NULL;}H->next=NULL;return H;
}node_p create_node(char* usrName, struct sockaddr_in cli_sockaddr){node_p p=(node_p)malloc(sizeof(node));if(p==NULL){printf("空间申请失败\n");return NULL;}strcpy(p->usrName, usrName);p->cli_sockaddr = cli_sockaddr;return p;
}void insert_tail(node_p H, char* usrName, struct sockaddr_in cli_sockaddr){if(H==NULL){printf("入参为空\n");return;}node_p p=H;while(p->next!=NULL){p=p->next;}node_p new = create_node(usrName, cli_sockaddr);new->next=p->next;p->next=new;
}/*   @brief  判断客户端信息是否已经保存在链表内@param  H 头结点cli_sockaddr 待判断的客户端信息@retval NULL 客户端信息不在链表内非空 客户端的用户名字符串指针
*/char* find(node_p H, struct sockaddr_in cli_sockaddr){if (H == NULL){printf("入参为空\n");return NULL;}if (H->next == NULL){// 链表为空return NULL;}node_p temp = H->next;while (temp != NULL){if (temp->cli_sockaddr.sin_addr.s_addr == cli_sockaddr.sin_addr.s_addr && temp->cli_sockaddr.sin_port == cli_sockaddr.sin_port){return temp->usrName;}temp = temp->next; }return NULL;
}/*   @brief  删除链表中指定的客户端信息@param  H 头结点cli_sockaddr 待删除的客户端信息@retval 无
*/void delete(node_p H, struct sockaddr_in cli_sockaddr){if (H == NULL){printf("入参为空\n");return;}node_p temp = H;while (temp->next->cli_sockaddr.sin_addr.s_addr != cli_sockaddr.sin_addr.s_addr || \temp->next->cli_sockaddr.sin_port != cli_sockaddr.sin_port)temp = temp->next;node_p p = temp->next;temp->next = temp->next->next;free(p);
}

客户端

#include <myhead.h>#define SER_PORT 8888
#define SER_IP "192.168.124.38"
#define CLI_PORT 6666
#define CLI_IP "192.168.125.117"
#define WBUFSIZE 128
#define RBUFSIZE 128int main(int argc, const char *argv[])
{int sockfd;char wbuf[WBUFSIZE] ={0};char rbuf[RBUFSIZE] ={0};struct sockaddr_in ser_sockaddr;struct pollfd pfds[2];sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd == -1){perror("socket");return -1;}ser_sockaddr.sin_family = AF_INET;ser_sockaddr.sin_port = htons(SER_PORT);ser_sockaddr.sin_addr.s_addr = inet_addr(SER_IP);pfds[0].fd = 0;pfds[0].events = POLLIN;pfds[1].fd = sockfd;pfds[1].events = POLLIN;printf("请输入聊天昵称->");fflush(stdout);//开始通信while(1){// 通信缓冲区memset(wbuf, 0, sizeof(wbuf));memset(rbuf, 0, sizeof(rbuf));// 阻塞等待事件发生poll(pfds, 2, -1);// 向服务器端发送消息if(pfds[0].revents == POLLIN){fgets(wbuf, sizeof(wbuf), stdin);wbuf[strlen(wbuf)-1] = 0;sendto(sockfd, wbuf, strlen(wbuf), 0, (struct sockaddr*)&ser_sockaddr, sizeof(struct sockaddr));if(strcmp(wbuf, "quit") == 0){close(sockfd);return 0;}}// 接收服务器消息if(pfds[1].revents == POLLIN){recvfrom(sockfd, rbuf, sizeof(rbuf), 0,NULL, NULL);printf("%s\n", rbuf);}}return 0;
}

相关文章:

UDP聊天室

服务器端 #include <myhead.h>#define SER_IP "192.168.124.38" #define SER_PORT 8888 #define RBUFSIZE 128 #define WBUFSIZE 128typedef struct node{char usrName[20];struct sockaddr_in cli_sockaddr;struct node* next; }node, *node_p;node_p create…...

LLM多模态——GPT-4o改变人机交互的多模式 AI 模型应用

1. 概述 OpenAI 发布了迄今为止最新、最先进的语言模型 – GPT-4o也称为“全“ 模型。这一革命性的人工智能系统代表了一次巨大的飞跃&#xff0c;其能力模糊了人类和人工智能之间的界限。 GPT-4o 的核心在于其原生的多模式特性&#xff0c;使其能够无缝处理和生成文本、音频…...

安卓手机APP开发__蓝牙功能概述

安卓手机&#xff21;&#xff30;&#xff30;开发&#xff3f;&#xff3f;蓝牙功能概述 目录 概述 基本内容 关键的类和接口 概述 安卓平台支持了蓝牙网络栈&#xff0c;它允许一个设备和其它的蓝牙设备进行无线的交换数据。 &#xff21;&#xff30;&#xff30;的框架…...

get和post的区别,二者是幂等的吗?

一、什么是幂等 所谓幂等性通俗的将就是一次请求和多次请求同一个资源产生相同的副作用。 维基百科定义&#xff1a;幂等&#xff08;idempotent、idempotence&#xff09;是一个数学与计算机学概念&#xff0c;常见于抽象代数中。 在编程中一个幂等操作的特点是其任意多次执…...

农场--Kruskal应用--c++

【题目要求】 农场里有一些奶牛&#xff0c;作为食物的草料不够了。农场主需要去别的农场借草料。该地区有N (2 < N < 2,000) 个农场&#xff0c;农场名称用数字N标识&#xff0c;农场之间的道路是双向的&#xff0c;一共有M (1 < M < 10,000)条道路&#xff0c;单…...

【Crypto】Rabbit

文章目录 一、Rabbit解题感悟 一、Rabbit 题目提示很明显是Rabbit加密&#xff0c;直接解 小小flag&#xff0c;拿下&#xff01; 解题感悟 提示的太明显了...

IRFB3207PBF TO-220 N沟道75V/180A 直插MOSFET场效应管

英飞凌&#xff08;Infineon&#xff09;的 IRFB3207PBF 是一款高性能的 N 沟道 MOSFET&#xff0c;适用于多种电子设备和系统中的高侧开关应用。以下是 IRFB3207PBF 的一些典型应用场景&#xff1a; 1. 电源管理&#xff1a;在电源管理系统中&#xff0c;IRFB3207PBF 可以作为…...

基于单张图片快速生成Metahuman数字人(模型贴图绑定)的工作流演示

基于单张图片快速生成Metahuman数字人&#xff08;模型贴图绑定&#xff09;的工作流演示 MetahumanModeler, 是我基于facebuilder以及metahuman的理解开发而成&#xff0c;插件可以基于单张图片生成metahuman拓扑结构的面部3d模型&#xff0c;同时生成对应的面部的贴图&#…...

MySQL数据库下的Explain命令深度解析

Explain是一个非常有的命令&#xff0c;可以用来获取关于查询执行计划的信息&#xff0c;以及如何解释输出。Explain命令是查看查询优化器如何决定执行查询的主要方法。这个功能有一定的局限性&#xff0c;并不总是会说出真相&#xff0c;但是它的输出是可以获取的最好信息&…...

防火墙技术基础篇:基于IP地址的转发策略

防火墙技术基础篇&#xff1a;基于IP地址的转发策略的应用场景及实现 什么是基于IP地址的转发策略&#xff1f; 基于IP地址的转发策略是一种网络管理方法&#xff0c;它允许根据目标IP地址来选择数据包的转发路径。这种策略比传统的基于目的地地址的路由更灵活&#xff0c;因…...

OpenFeign快速入门 替代RestTemplate

1.引入依赖 <!--openFeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--负载均衡器--><dependency><groupId>org.spr…...

自动化测试--利用pytest实现整条业务链路测试

​ 概述 前面一章讲解了单个接口的测试&#xff0c;但是实际项目中&#xff0c;因为权限和登录状态的限制&#xff0c;大部分接口没办法直接访问到&#xff0c;这时候我们想访问到一个系统的接口&#xff0c;就需要模拟用户登录拿到用户的token和所拥有的权限之后再将这些信息…...

学习其他推理判断

学习其他推理判断 1.类比推理1.1语义关系1.2逻辑关系1.3 语法关系2.定义判断3.翻译推理3.1前推后:A→B3.2后推前:B→A3.3推理规则4.组合排列5.日常结论6.逻辑论证6.1削弱题型6.2加强题型7.原因解释1.类比推理 类比推理:给出一组相关的词,通过观察分析,在备选答案中找出一组…...

Centos7环境下MySQL5.7.38 安装开源审计插件 mysql-audit

MySQL安装开源审计插件 mysql-audit MySQL 5.7.38安装审计插件 mysql-audit安装MySQL1.查看Linux服务器版本和glibc版本2.根据自己的系统下载对应的MySQL版本&#xff0c;由于mysql-audit并不支持所有版本的MySQL&#xff0c;所以在确定MySQL版本之前请注意下插件支持的MySQL版…...

基于深度学习的表情识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 随着人工智能技术的快速发展&#xff0c;表情识别成为了人机交互领域的一个研究热点。表情识别技术旨…...

Debug-010-git stash的用法及使用场景

问题原因&#xff1a; 其实也不是最近&#xff0c;就是之前就碰到过这个问题&#xff0c;那就是我正在新分支开发新功能&#xff0c;开发程度还没有到可以commit的程度&#xff0c;我不想提交(因为有些功能没有完全实现&#xff0c;而且没有自测的话很容易有问题&#xff0c;提…...

RustGUI学习(iced/iced_aw)之扩展小部件(二十五):如何使用tab部件来创建tab多页面切换?

前言 本专栏是学习Rust的GUI库iced的合集,将介绍iced涉及的各个小部件分别介绍,最后会汇总为一个总的程序。 iced是RustGUI中比较强大的一个,目前处于发展中(即版本可能会改变),本专栏基于版本0.12.1. 概述 这是本专栏的第二十五篇,主要讲述tab页面切换部件的使用,会结…...

P2P服务端模型配合 Tool.net P2pServerAsync 类使用

Tool.Net 支持的 P2P 服务器模型实例 说明服务器部分相关代码相关调用实例Tcp版本Udp版本 最后附一张思维图 说明 当前文章&#xff0c;仅是Tool.Net 开源库的一个缩影。本次更新V5.0版本以上提供支持。可以提供简单实现P2P功能用于业务开发。 服务器部分相关代码 完整代码&…...

Python语法学习之 - 生成器表达式(Generator Expression)

第一次见这样的语法 本人之前一直是Java工程师&#xff0c;最近接触了一个Python项目&#xff0c;第一次看到如下的代码&#xff1a; i sum(letter in target_arr for letter in source_arr)这条语句是计算source 与 target 数组中有几个单词是相同的。 当我第一眼看到这样…...

docker所在磁盘空间不足 迁移数据

1.查看原始目录docker info | grep "Docker Root Dir" 一般在/var/lib/docker 2.停止docker service docekr stop 3.移动数据 注意 移动前不要创建docker目录&#xff01; mv /var/lib/docker /home/docker 4.进入目录查看是否与原始目录相同&#xff0c;确认一…...

利用 AI Agent 优化日常办公自动化流程

AI Agent优化办公自动化流程的核心逻辑是「人定规则&#xff0c;AI跑流程」‌&#xff0c;通过把重复、步骤明确的工作交给AI Agent自主执行&#xff0c;实现提效降本&#xff0c;具体可以按照以下方法落地&#xff1a;一、先明确落地逻辑把目标工作拆成「触发条件→执行步骤→…...

书匠策AI到底有多懂毕业生?一个论文小白的“开挂“实录,看完你也想试!

嗨&#xff0c;各位正在为毕业论文头秃的宝子们&#xff01;&#x1f44b; 我是你们的论文科普搭子&#xff0c;今天不讲枯燥的写作技巧&#xff0c;直接给大家安利一个我最近发现的"宝藏神器"——书匠策AI&#xff08; 官网直达&#xff1a;www.shujiangce.com&…...

线粒体氧化磷酸化的新靶点:S-Gboxin的发现与研究进展

在肿瘤治疗的探索历程中&#xff0c;科学家们始终在寻找能够精准打击癌细胞而又最大限度保护正常组织的新型药物。2019年&#xff0c;一项发表在Nature杂志上的研究引起了学界广泛关注——施宇峰团队首次报道了Gboxin这一化合物的发现与独特的作用机制[1]。作为Gboxin的代谢稳定…...

Windows 10/11 HTTPS抓包证书信任配置全指南

1. 为什么HTTPS抓包在Win10/Win11上总卡在“证书不信任”这一步&#xff1f;你是不是也遇到过这样的场景&#xff1a;在Windows 10或Windows 11上装好Charles&#xff0c;勾选了SSL Proxying&#xff0c;手机连上Wi-Fi、设置代理指向本机IP和8888端口&#xff0c;结果打开任何H…...

第一学期结果

关注 1.从安涛老师前三期视频中了解了方向2.从b站了解了555的内部结构3.仿真。4.低通滤波器的基本原理&#xff1a;一、核心定义只允许低频信号顺利通过&#xff0c;阻挡、衰减高频信号的电路。 你电路里作用&#xff1a;滤掉方波里的高频谐波&#xff0c;留下低频基波&#xf…...

KAN网络实战:5分钟看懂如何用它‘可视化’发现物理定律(以安德森定域化为例)

KAN网络&#xff1a;用可视化方法发现物理定律的AI协作者 在科学研究的前沿&#xff0c;物理学家们常常需要从海量数据中识别出隐藏的规律和模式。传统的人工智能方法虽然能够提供预测结果&#xff0c;却往往难以解释其内部机制&#xff0c;这让科学家们难以信任和验证这些&quo…...

从能算到秒杀:完全平方数与最少数量的数学真相

LeetCode Hot 100 刷题笔记 第 15 篇如果说「跳跃游戏 II」是在教你 什么时候不得不跳&#xff0c;那 279. 完全平方数​ 就是在考你&#xff1a;最少能用几个平方数&#xff0c;凑出一个整数&#xff1f;这也是我第一次意识到&#xff1a;有些动态规划&#xff0c;其实是在替…...

Unity重型战士Mecanim动画包:开箱即用的战斗动画解决方案

1. 这套动画包到底解决了什么实际问题&#xff1f;在Unity项目开发中&#xff0c;我见过太多团队卡在“角色动不起来”这一步——不是程序写不出状态机&#xff0c;而是美术资源交付后&#xff0c;Animator Controller里一堆红色警告&#xff1a;Missing Avatar、Clip not mapp…...

美国签证预约机器人:3分钟掌握24小时智能抢号终极方案

美国签证预约机器人&#xff1a;3分钟掌握24小时智能抢号终极方案 【免费下载链接】us-visa-bot US Visa Bot 项目地址: https://gitcode.com/gh_mirrors/us/us-visa-bot 还在为美国签证面试预约的漫长等待而烦恼吗&#xff1f;面对有限的面试名额和激烈的竞争环境&…...

建筑数据驱动预测控制方法应用【附模型】

✨ 长期致力于建筑热动态、阻容模型、数据驱动预测控制、控制器实施、人工智能研究工作&#xff0c;擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流&#xff0c;点击《获取方式》 &#xff08;1&#xff09;简化阻容模型结构与贝叶…...