坐牢第二十七天(聊天室)
基于UDP的网络聊天室
一.项目需求:
1.如果有用户登录,其他用户可以收到这个人的登录信息
2.如果有人发送信息,其他用户可以收到这个人的群聊信息
3.如果有人下线,其他用户可以收到这个人的下线信息
4.服务器可以发送系统信息

二.代码
udp.h
#ifndef UDP_H
#define UDP_H
#include <myhead.h>
#define SER_PORT 8888 // 服务器端口号
#define SER_IP "192.168.0.105" // 服务器ip地址
#define CLI_PORT 5555 // 客户端端口号
#define CLI_IP "192.168.0.105" // 客户端地址
//枚举
enum type_t
{Login,Chat,Quit,
};
typedef struct MSG
{char type;//Login名字 Chat内容 Quit退出 //内容编号char name[32];//名字char text[128];//内容
}msg_t;
typedef struct NODE//链表
{struct sockaddr_in cin;struct NODE *next;
}Node,*Nodeptr;
//创建头节点函数
Nodeptr create();
//登录的函数
//功能:
//1.将新登录的用户转发给所有已经登录的用户(遍历链表发送谁登录的消息)
//2.创建新节点来保存新登录用户的信息,链接到链表尾就可以
void do_login(int sockfd,msg_t msg,Nodeptr p,struct sockaddr_in cin);
//群聊的函数
//功能:将客户端发来的聊天内容转发给所有已登录的用户,除了发送聊天内容的用户以外
void do_chat(int sockfd,msg_t msg,Nodeptr p,struct sockaddr_in cin);
//退出函数
//功能:
//1.将谁退出的消息转发给i所有用户
//2.将链表中保存这个推出的用户信息的节点删除
void do_quit(int sockfd,msg_t msg,Nodeptr p,struct sockaddr_in cin);
#endif
udp.c
#include "udp.h"
// 定义创建头节点函数
Nodeptr create()
{Nodeptr p = (Nodeptr)malloc(sizeof(Node));if (p == NULL){perror("malloc error");return NULL;}p->next = NULL;return p;
}
// 定义登录的函数
void do_login(int sockfd, msg_t msg, Nodeptr p, struct sockaddr_in cin)
{sprintf(msg.text, "%s 以上线", msg.name);while (p->next != NULL){p = p->next;sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->cin), sizeof(p->cin));}Nodeptr new = (Nodeptr)malloc(sizeof(Node));// 初始化new->cin = cin;new->next = NULL;// 链接到链表尾p->next = new;return;
}
// 定义群聊的函数
void do_chat(int sockfd, msg_t msg, Nodeptr p, struct sockaddr_in cin)
{// 遍历链表while (p->next != NULL){p = p->next;if (memcmp(&(p->cin), &cin,sizeof(cin))!= 0){sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->cin), sizeof(p->cin));}}return;
}
// 定义退出函数
void do_quit(int sockfd, msg_t msg, Nodeptr p, struct sockaddr_in cin)
{sprintf(msg.text, "%s 以下线", msg.name);while (p->next != NULL){if (memcmp(&(p->cin), &cin,sizeof(cin)) == 0){Nodeptr q = NULL;q = p->next;p->next = q->next;free(q);q = NULL;}else{p = p->next;sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->cin), sizeof(p->cin));}}return;
}
sen.c
// 服务器
#include "udp.h"
int main(int argc, char const *argv[])
{// 创建UDP套接字int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){perror("socket error");exit(-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);// 定义保存客户端网络信息的结构体struct sockaddr_in cin;cin.sin_family = AF_INET;cin.sin_port = htons(CLI_PORT);cin.sin_addr.s_addr = inet_addr(CLI_IP);socklen_t len = sizeof(cin);// 绑定套接字和服务器网络信息的结构体bind(sockfd, (struct sockaddr *)&sin, sizeof(sin));printf("绑定成功!\n");msg_t msg;Nodeptr p = create();char s[20]="";while (1){if (recvfrom(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&cin, &len) < 0){perror("recvfrom error");return -1;}if (msg.type == Login){strcpy(msg.text, "以上线");printf("ip:%s pord:%d name:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), msg.name);printf("状态:%s\n", msg.text);//调用登录函数do_login(sockfd, msg, p, cin);}else if (msg.type == Chat){//调用群聊函数do_chat(sockfd, msg, p, cin);}else if (msg.type == Quit){strcpy(msg.text, "以下线");printf("ip:%s pord:%d name:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), msg.name);printf("状态:%s\n", msg.text);//调用退出函数do_quit(sockfd, msg, p, cin);}}close(sockfd);return 0;
}
rec.c
// 客户端
#include "udp.h"
int main(int argc, char const *argv[])
{int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){perror("socket error");exit(-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 len = sizeof(sin);msg_t msg;// 先执行登录操作printf("请登录:\n");msg.type = Login;printf("请输入用户名:");fgets(msg.name, 32, stdin);msg.name[strlen(msg.name) - 1] = 0;// 发送登录消息if (sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&sin, len) < 0){perror("sendto err");exit(-1);}//创建多进程pid_t pid = fork();if (pid < 0){perror("fork error");exit(-1);}else if (pid == 0){while (1){if (recvfrom(sockfd, &msg, sizeof(msg), 0, NULL, NULL) < 0){perror("recvfrom error");return -1;}printf("[%s]:%s\n", msg.name, msg.text);}}else{while (1){fgets(msg.text, sizeof(msg.text), stdin);msg.text[strlen(msg.text) - 1] = 0;if (strcmp(msg.text, "quit") == 0){msg.type = Quit;sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&sin, len);kill(pid, SIGKILL);wait(NULL);exit(EXIT_SUCCESS);}else{msg.type = Chat;}// 发送消息sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&sin, len);}}close(sockfd);return 0;
}
相关文章:
坐牢第二十七天(聊天室)
基于UDP的网络聊天室 一.项目需求: 1.如果有用户登录,其他用户可以收到这个人的登录信息 2.如果有人发送信息,其他用户可以收到这个人的群聊信息 3.如果有人下线,其他用户可以收到这个人的下线信息 4.服务器可以发送系统信息…...
C++自学笔记33(数据类型总结与变量)
数据类型 类型位范围char1 个字节-128 到 127 或者 0 到 255unsigned char1 个字节0 到 255signed char1 个字节-128 到 127int4 个字节-2147483648 到 2147483647unsigned int4 个字节0 到 4294967295signed int4 个字节-2147483648 到 2147483647short int2 个字节-32768 到…...
游戏引擎phaser.js3的使用之玩家和静态物理组碰撞
玩家和静态物理组都加载好了,那就应该开始操作玩家动态和静态之间的碰撞了 下面是通过点击图片按钮来操作碰撞的 sky.on(pointerdown, function () { console.log(图片被点击了!); }) 图片点击后让动态的玩家和静态的物理组碰撞,就可以这…...
springboot整合mybatis以及mybatis-plus 开发
一、springboot整合mybatis 1.注解版 1.1 导入坐标 <dependencies><!--mybatis坐标--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</…...
大语言模型微调框架Unsloth:简化模型微调流程,提升模型性能
Unsloth 将 Llama-3、Mistral、Phi-3 和 Gemma 等大型语言模型的微调速度提高了 2 倍,内存使用量减少了 70%,而且准确性不会降低! 特点 通过手动派生所有计算繁重的数学步骤和手写 GPU 内核,unsloth 可以在不更改任何硬件的情况…...
IPD-华为研发之道分析与理解
关于西方众多优秀的管理模式、理论我们学习过,也借鉴以及实践过,拿到《IPD-华为研发之道》通读研习后,正如书中所述,IPD是一套产品开发的模式、理念与方法,IPD思想,流程和方法是诸多成功企业优秀实践的经验…...
时空序列顶会文章
ICLR 2024 时间序列(Time Series)高分论文 - 知乎 (zhihu.com) ICML2024全部论文 icml.cc/virtual/2024/papers.html...
C语言-使用指针数组作为函数参数,实现对10个字符串进行排序
使用指针数组作为函数参数,实现对10个字符串进行排序 1.输入 lisi hahaha hehehe helloa leihoua lisi nihaoa wangwu ajax bureau2.输出 ajax bureau hahaha hehehe helloa leihoua lisi lisi nihaoa wangwu3.程序: #define _CRT_SECURE_NO_WARNING…...
???ABC366:F - Maximum Composition(dp,无序:贪心排序)
问题陈述 给你 NN 个线性函数 f1,f2,…,fNf1,f2,…,fN ,其中 fi(x)AixBifi(x)AixBi . 求由 KK 组成的序列 p(p1,p2,…,pK)p(p1,p2,…,pK) 中 fp1(fp2(…fpK(1)…))fp1(fp2(…fpK(1)…)) 的最大可能值。介于 11 和 NN (含)之间的个不…...
unity项目打包为webgl后应用于vue项目中(iframe模式)的数据交互
参考文章: 1.Unity打包WebGL: 导入Vue 2.unity文档-WebGL:与浏览器脚本交互 3.unity与vue交互(无第三方插件) 目录 一、前期工作1.新建.jslib文件2.新建.cs脚本3. 新建一个Text对象和button按钮对象4.添加脚本空对象UIEvent5.导出unity为w…...
【数据结构与算法 | 图篇】Bellman-Ford算法(单源最短路径算法)
1. 前言 前文的迪杰斯特拉算法不能求解有负边的图的最短路径的问题。而此文的Bellman-Ford可以处理含负权边的图算法,并且能检测出图中是否存在负环(权重和为负数的环). 2. 基本思想 1. 初始化: 对于所有顶点 v ∈ V \ {s}&am…...
Python | Leetcode Python题解之第336题回文对
题目: 题解: class Solution:def palindromePairs1(self, words: List[str]) -> List[List[int]]:# 核心思想--枚举前缀和后缀# 如果两个字符串k1,k2组成一个回文字符串会出现三种情况# len(k1) len(k2),则需要比较k1 k2[::-1]# len(k1…...
C语言家教记录(六)
导语 本次授课的内容如下:指针,指针和数组 辅助教材为 《C语言程序设计现代方法(第2版)》 指针 指针变量 计算机按字节划分地址,每个地址访问一个字节 指针变量指向变量的地址,指的是变量第一个字节的…...
C++竞赛初阶L1-11-第五单元-for循环(25~26课)519: T454430 人口增长问题
题目内容 假设目前的世界人口有 x 亿,按照每年 0.1% 的增长速度,n 年后将有多少人? 输入格式 一行两个正整数 x 和 n,之间有一个空格。其中,1≤x≤100,1≤n≤100。 输出格式 一行一个数,表示答案。以亿…...
demo测试
目录 接口commonCodeGenerator entityuser mapperUserMapper controllerUserController serviceUserServiceimplUserServiceImpl mapper.xmlpom.xmlapplication.yml 接口 common CodeGenerator package com.llz.demo.common;import com.baomidou.mybatisplus.core.exceptions…...
TinTinLand Web3 + DePIN 共学月|深入探索 DePIN 项目,全景分析去中心化网络未来
「TinTinLand Web3 主题共学月」是由 TinTinLand 每月发起的主题学习活动,携手知名项目共同打造一个系统化、互动性强的学习平台,帮助开发者不断提升技能,紧跟 Web3 技术的前沿发展。活动通过演示视频、学习打卡、模拟环境、实际操作等多种方…...
Java并发编程(六)
1、java 中有几种方法可以实现一个线程 继承 Thread 类实现 Runnable 接口实现 Callable 接口,需要实现的是 call() 方法 2、如何停止一个正在运行的线程 使用共享变量的方式 在这种方式中,之所以引入共享变量,是因为该变量可以被多个执行…...
k8s对外服务之Ingress
目录 1.Ingress 简介 2.Ingress 组成 3.Ingress-Nginx 工作原理 4.部署 nginx-ingress-controller 5.总结 1.Ingress 简介 service的作用体现在两个方面,对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了…...
使用Python+moviepy在视频画面上绘制边框
一、 使用VideoFileClip对象的的fx函数设置vfx.margin,在视频画面上绘制边框 from moviepy.editor import * mvVideoFileClip(/home/Download/leaves.mp4) mv2mv.fx(vfx.margin,mar3,color(0,0,255),opacity0.5) # 绘制边框# mar3 :边框宽度3像素&#…...
灵办AI探索之旅:颠覆传统的代码开发工具
前言 灵办AI是一个先进的人工智能工具,专注于提高软件开发和项目管理的效率。其核心功能包括代码生成、优化、评估和自动化修复,旨在帮助开发者和团队提升开发速度和代码质量。 体验地址:https://ilingban.com/browser_extension/?fromjj …...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
小智AI+MCP
什么是小智AI和MCP 如果还不清楚的先看往期文章 手搓小智AI聊天机器人 MCP 深度解析:AI 的USB接口 如何使用小智MCP 1.刷支持mcp的小智固件 2.下载官方MCP的示例代码 Github:https://github.com/78/mcp-calculator 安这个步骤执行 其中MCP_ENDPOI…...
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...
