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

UDP实现聊天室

现象:

源码:

服务器:

#include<myhead.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;
}

客户端:

#include <myhead.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实现聊天室

现象&#xff1a; 源码&#xff1a; 服务器&#xff1a; #include<myhead.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//链…...

排序算法:如冒泡排序、插入排序、选择排序、快速排序、归并排序

冒泡排序&#xff08;Bubble Sort&#xff09;&#xff1a;冒泡排序是一种简单的排序算法。它通过反复交换相邻的元素&#xff0c;将最大的元素逐步“浮”到数组的末尾。基本思想是每次比较相邻的两个元素&#xff0c;如果顺序不对就进行交换&#xff0c;直到整个数组有序。时间…...

深度学习pytorch——GPU加速(持续更新)

使用 .to(device)&#xff0c;以前使用 .cuda() &#xff0c;但是现在基本不使用了。 代码示例&#xff1a; 查看电脑GPU运行情况&#xff1a; 使用Ctrl Shift ESC快捷键&#xff1a;...

StringRedisTemplate

Redis快速入门 3.2.3.StringRedisTemplate 为了节省内存空间&#xff0c;我们可以不使用JSON序列化器来处理value&#xff0c;而是统一使用String序列化器&#xff0c;要求只能存储String类型的key和value。当需要存储Java对象时&#xff0c;手动完成对象的序列化和反序列化。…...

Linux cp、mv命令显示进度条

1.advcpmv 平常使用cp 拷贝大文件时&#xff0c;看不到多久可以完成&#xff0c;虽然加上-v参数也只能看到正在拷贝文件&#xff0c;那就使用以下方法实现 git clone https://github.com/jarun/advcpmv.git cd advcpmv/ bash install.shmv ./advcp /usr/local/bin/ mv ./advmv …...

在Java中使用Apache POI保留Excel样式合并多个工作簿

背景 在日常工作中&#xff0c;我们经常需要将多个Excel文件合并成一个&#xff0c;同时保留原有的样式和格式。Apache POI是一个流行的Java库&#xff0c;用于读取和写入Microsoft Office格式的文件&#xff0c;包括Excel。然而&#xff0c;仅仅使用Apache POI的基本功能进行…...

Nomachine远程黑屏通用处理方法

Nomachine远程黑屏通用处理方法 文章目录 前言正文解决步骤 总结 前言 NoMachine是一种远程桌面软件&#xff0c;它允许用户通过互联网或局域网连接到远程计算机&#xff0c;并在本地计算机上使用远程计算机的桌面环境和应用程序。它提供了高性能的图形渲染和低延迟的响应&…...

基于51单片机数控直流电压源proteus仿真LCD显示+程序+设计报告+讲解视频

基于51单片机数控直流电压源proteus仿真LCD显示( proteus仿真程序设计报告讲解视频&#xff09; 仿真图proteus7.8及以上 程序编译器&#xff1a;keil 4/keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;S0072 讲解视频 基于51单片机数控直流电压源proteus仿真程序…...

[Linux]文件缓冲区

文件fd 输出重定向除了用dup2()改变数组下标外&#xff0c;还可以用命令来完成 所有的命令执行&#xff0c;都必须有操作系统将其运行起来变成进程&#xff0c;然后根据>>, <<来判断是输入重定向&#xff0c;还是输出重定向。 缓冲区 之所以有缓冲区&#xff0…...

ARM:按键中断

key_inc.c #include"key_inc.h"void key1_it_config(){//使能GPIOF外设时钟RCC->MP_AHB4ENSETR | (0x1<<5);//将PF9设置为输入模式GPIOF->MODER & (~(0x3<<18));//设置由PF9管脚产生EXTI9事件EXTI->EXTICR3 & (~(0XFF<<8));EXTI…...

JavaScript高级(五)--柯西化函数

柯里化 定义 首先&#xff0c;我们参照维基百科给出的定义&#xff1a; 在计算机科学中&#xff0c;柯里化&#xff08;英语&#xff1a;Currying&#xff09;&#xff0c;又译为卡瑞化或加里化&#xff0c;是把接受多个参数的函数变换成接受一个单一参数&#xff08;最初函数…...

带3090显卡的Linux服务器上部署SDWebui

背景 一直在研究文生图&#xff0c;之前一直是用原始模型和diffuser跑SD模型&#xff0c;近来看到不少比较博主在用 SDWebui&#xff0c;于是想着在Linux服务器上部署体验一下&#xff0c;谁知道并没有想象的那么顺利&#xff0c;还是踩了不少坑。记录一下过程&#xff0c;也许…...

37、Linux中Xsync数据同步备份工具

37、Linux中Xsync数据同步备份工具 一、介绍二、配置集群hostname三、修改xsync文件四、赋权五、安装Rsync六、验证一七、配置免密登录1、生成rsa密钥2、copy机器自身公钥到目标机器3、.ssh/文件目录赋权 八、验证二 ⚠️ 注&#xff1a;本文全程在普通用户下操作&#xff0c;…...

网络基础:构建你的数字世界之桥

I. 引言 A. 什么是网络&#xff1f; 网络是由各种电子设备通过通信线路或无线电波连接起来&#xff0c;以便彼此之间进行数据交换和资源共享的系统。在当今数字化时代&#xff0c;网络已经成为我们生活和工作中不可或缺的一部分&#xff0c;无论是互联网、局域网还是无线通信…...

Python 全栈系列236 rabbit_agent搭建

说明 通过rabbit_agent, 以接口方式实现对队列的标准操作&#xff0c;将pika包在微服务内&#xff0c;而不必在太多地方重复的去写。至少在服务端发布消息时&#xff0c;不必再去考虑这些问题。 在分布式任务的情况下&#xff0c;客户端本身会启动一个持续监听队列的客户端服…...

管理自由,体验简单,使用安全 | 详解威联通全套多用户多权限管理方案【附TS-466C产品介绍】

管理自由&#xff0c;体验简单&#xff0c;使用安全 | 详解威联通全套多用户多权限管理方案【附TS-466C产品介绍】 哈喽小伙伴们好&#xff0c;我是Stark-C~。今天我们来解决一个之前评论区多次被提及的问题--多用户权限管理。 对于我们NAS用户来说&#xff0c;基本都会面临这…...

【Redis】优惠券秒杀

全局唯一ID 全局唯一ID生成策略&#xff1a; UUIDRedis自增snowflake算法数据库自增 Redis自增ID策略&#xff1a;每天一个key&#xff0c;方便统计订单量ID构造是 时间戳 计数器 Component public class RedisIdWorker {// 2024的第一时刻private static final long BEGIN…...

【几何】平面方程

文章目录 平面方程一般式截距式点法式法线式 平面方程 平面方程是用一个方程来表示平面&#xff0c;平面上的所有点代入方程&#xff0c;方程都成立。因为用法的不同&#xff0c;平面方程一般有四种表现形式。 一般式 设 n ⃗ ( A , B , C ) \vec n(A,B,C) n (A,B,C) 为平…...

macOS访问samba文件夹的正确姿势,在哪里更改“macOS的连接身份“?还真不好找!

环境&#xff1a;路由器上需要身份认证的Mini NAS macOS Sonoma 14 这是一个非常简单的问题&#xff0c;但解决方法却藏得比较深&#xff0c;不够直观&#xff0c;GPT也没有给出明确的解决提示&#xff0c;特意记录一下。 macOS很多地方都很自动&#xff0c;有时候让人找不到设…...

linux进程切换

内核堆栈&#xff1a;每个进程在内核模式下运行时都有自己的内核堆栈。这个堆栈保存了进程在内核模式下的运行状态&#xff0c;包括函数调用时传递的参数、局部变量和返回地址等。 用户态与内核态&#xff1a;进程通常在用户态下运行&#xff0c;当执行系统调用或响应中断时进…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...