坐牢第二十七天(聊天室)

基于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;
}

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

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

相关文章

算法工程师第四十天(647. 回文子串 516.最长回文子序列 动态规划总结篇 )

参考文献 代码随想录 一、回文子串 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 示例 1&#xff1a; 输入&#xff1a;s "abc"…

【stm32项目】多功能智能家居室内灯光控制系统设计与实现(完整工程资料源码)

多功能智能家居室内灯光控制系统设计与实现 目录&#xff1a; 目录&#xff1a; 前言&#xff1a; 一、项目背景与目标 二、国内外研究现状&#xff1a; 2.1 国内研究现状&#xff1a; 2.2 国外研究现状&#xff1a; 2.3 发展趋势 三、硬件电路设计 3.1 总体概述 3.2 硬件连接总…

图像压缩算法

8.1 JPEG压缩 (JPEG Compression) 介绍 JPEG&#xff08;Joint Photographic Experts Group&#xff09;压缩是最常用的有损图像压缩算法之一。它通过减少图像中的冗余数据来实现高效压缩&#xff0c;特别适用于自然图像。 原理 JPEG压缩的基本步骤包括颜色空间转换、离散余…

WPF篇(18)-DataGrid数据表格控件+ComboBox下拉框控件

DataGrid数据表格控件 DataGrid是一个可以多选的数据表格控件。所以&#xff0c;它继承一个支持多选的父类——MultiSelector。 public abstract class MultiSelector : Selector {protected MultiSelector();public IList SelectedItems { get; }protected bool CanSelectMu…

Python学习day16-类与对象

这里写目录标题 类示例 成员方法self关键字 类与对象构造方法其他类内置方法&#xff08;魔术方法&#xff09;_str_符号_Lt_符号le小于等于比较eq比较运算小结 类 在Python中&#xff0c;class&#xff08;类&#xff09;是一种用于创建对象的模板或蓝图。它封装了数据&#…

基于Django的停车场车辆出入管理系统,可识别车牌图片

研究背景 随着城市化进程的加快&#xff0c;车辆数量不断增加&#xff0c;停车场的管理成为一个日益重要的课题。传统的停车场管理系统依赖人工登记和监控&#xff0c;不仅效率低下&#xff0c;而且容易出现疏漏和错误&#xff0c;难以满足现代社会对停车场管理智能化、高效化…

STM32标准库学习笔记-3.外部中断

参考教程&#xff1a;【STM32入门教程-2023版 细致讲解 中文字幕】 中断 中断含义&#xff1a;在计算机执行主程序运行过程中&#xff0c;出现了特定的中断触发条件&#xff08;中断源&#xff09;&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序&…

2024 国内自闭症学校排名榜:突破边界,创造无限可能

在 2024 年&#xff0c;当家长们面对国内自闭症学校的排名榜时&#xff0c;心中或许充满了期待与困惑。然而&#xff0c;这些排名榜虽然能提供一定的参考&#xff0c;但绝不能成为选择学校的唯一依据。家长们更需要深入了解每所学校的真实情况&#xff0c;通过线下考察&#xf…

python及pycharm安装配置

PS&#xff1a;这篇是对于初学者的python以及pycharm配置教程&#xff0c;配置完成后可以直接看我的python学习笔记来进行python全套学习&#xff0c;现在已更新第一部分。 Python学习笔记&#xff08;一&#xff09;-CSDN博客 目录 一、python以及pycharm的安装配置 1.1 py…

Nuxt3:构建的时候报错Search string not found: “for (const existingRoot of buildInfoVersionMap.roots)

我们完成初步页面开发后&#xff0c;需要构建下项目生成我们需要的页面&#xff0c;在执行构建的时候报错&#xff1a; 找了很多资料&#xff0c;这个问题是由于 vue-tsc v1 版本引起&#xff0c;只需要将 vue-tsc 升级到v2 即可 我们在执行删除的时候&#xff0c;结果发现它…

【MySQL】数据库约束

系列文章目录 第一章 数据库基础 第二章 数据库基本操作 文章目录 系列文章目录前言约束关键字一览NOT NULLUNIQUEDEFAULTPRIMARY KEY自增主键 FOREIGN KEY总结 前言 在学习了数据库的增删改查操作之后&#xff0c;接下来就需要进阶的学习关键字来完善SQL语句的条件。学习数据…

数据结构----链表

一丶概念 链表又称单链表、链式存储结构&#xff0c;用于存储逻辑关系为“一对一”的数据。 和顺序表不同同&#xff0c;使用链表存储数据&#xff0c;不强制要求数据在内存中集中存储&#xff0c;各个元素可以分散存储在内存中。 二丶特点 特点&#xff1a;内存不连…

DolphinScheduler集群部署问题(趟坑)总结

目录 官方文档 官方项目地址 问题解决 官方文档 DolphinScheduler | 文档中心 (apache.org) 官方项目地址 部署及使用过程中的问题可以参见项目Issue:Issues apache/dolphinscheduler GitHub GitHub - apache/dolphinscheduler at 3.2.2-release 问题解决 1、JVM在运…

Simple RPC - 05 从零开始设计一个客户端(下)_ 依赖倒置和SPI

文章目录 Pre概述依赖倒置原则与解耦设计与实现1. 定义接口来隔离调用方与实现类2. 实现类DynamicStubFactory3. 调用方与实现类的解耦 依赖注入与SPI的解耦依赖注入SPI&#xff08;Service Provider Interface&#xff09; 总结 Pre Simple RPC - 01 框架原理及总体架构初探 …

网络编程:OSI协议,TCP/IP协议,IP地址,UDP编程

目录 国际网络通信协议标准&#xff1a; 1.OSI协议&#xff1a; 2.TCP/IP协议模型&#xff1a; 应用层 &#xff1a; 传输层&#xff1a; 网络层&#xff1a; IPV4协议 IP地址 IP地址的划分&#xff1a; 公有地址 私有地址 MA…

dotnet常用命令详解

命令预览 基础命令 new&#xff1a;创建项目 restore&#xff1a;恢复依赖 build&#xff1a;编译项目 publish&#xff1a;生成项目需要的文件准备发布项目 run&#xff1a;运行项目 test&#xff1a;测试项目 vstest&#xff1a;从指定的程序集中运行测试 pack&#…

升级阿里云linux服务器上的php版本

查看已安装的php软件包 [rootiZbp13pl2v34qj0thwq9aiZ ~]# rpm -qa|grep php php74-php-common-7.4.26-1.el7.remi.x86_64 oniguruma5php-6.9.7.1-1.el7.remi.x86_64 php74-php-gd-7.4.26-1.el7.remi.x86_64 php74-php-opcache-7.4.26-1.el7.remi.x86_64 php74-php-json-7.4.2…

记录|Git工具——下载GitHub项目

目录 前言一、Step 1. 下载Git二、Step2. 用Git Bash 下载到本地更新时间 前言 参考文章&#xff1a; 1、如何使用Git将Github项目拉到本地 2、git 安装、创建仓库、上传项目、克隆下载、常用命令 – 一篇文章总结&#xff08;适用github / gitee&#xff09; 3、Git的使用【入…

政策驱动,科技引领,漫途信息化监测方案守护农村饮水安全!

近日&#xff0c;山西省人民政府正式发布《山西省农村供水高质量发展规划》&#xff0c;明确到2030年&#xff0c;全面实现农村24小时供水&#xff0c;县域农村饮水安全标准化建设达标率力争达到80%&#xff0c;基本实现农村供水城市化、城乡供水均等化。 现阶段部分地区受…

ArcGIS简单介绍

ArcGIS体系结构 &#xff08;1&#xff09;GIS Server 宿主各种GIS资源&#xff0c;将他们封装为服务提供给客户端应用。GIS Server分为两部分&#xff1a;Server Object Manager&#xff08;SOM&#xff09;和Server Object Containers&#xff08;SOCs&#xff09;。一个SO…