3.23项目:聊天室

1、 基于UDP的网络聊天室

项目需求:

  1. 如果有用户登录,其他用户可以收到这个人的登录信息
  2. 如果有人发送信息,其他用户可以收到这个人的群聊信息
  3. 如果有人下线,其他用户可以收到这个人的下线信息
  4. 服务器可以发送系统信息

服务器

#include <myhead.h>//链表结构体
typedef struct Node
{char name[20];struct sockaddr_in cin;struct Node *next;   //指针域
}node,*node_p;//数据结构体
struct msgTyp
{char type;char usrName[20];char msgText[1024];
};//创建链表头结点
node_p create_head()
{node_p L = (node_p)malloc(sizeof(node));if(L == NULL){printf("空间申请失败\n");return NULL;}L->next = NULL;return L;
}//创建结点
node_p create_node(char *name,struct sockaddr_in cin)
{node_p new = (node_p)malloc(sizeof(node));if(new == NULL){printf("空间申请失败\n");return NULL;}strcpy(new->name,name);new->cin = cin;return new;
}//头插
void insert(node_p L,char *name,struct sockaddr_in cin)
{if(L == NULL){printf("入参为空\n");return;}node_p new = create_node(name,cin);new->next = L->next;L->next = new;
}//按姓名删除
void delete(node_p L,char *name)
{if(L == NULL){printf("入参为空\n");return;}node_p p = L;while(p != NULL){if(strcmp(p->next->name,name) == 0){node_p del = p->next;free(del);p->next = p->next->next;break;}p = p->next;}
}int main(int argc, const char *argv[])
{//定义结构体变量node link;struct msgTyp msg;//创建链表node_p L = create_head();//创建套接字int sfd = socket(AF_INET,SOCK_DGRAM,0);if(sfd == -1){perror("socket error");return -1;}//判断是否有外部传参if(argc < 3){printf("请输入IP和端口号\n");return -1;}//端口号快速重用int reuse = 1;if(setsockopt(sfd,SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1){perror("setsockopt error");return -1;}//填写地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(atoi(argv[2]));sin.sin_addr.s_addr = inet_addr(argv[1]);//绑定IP和端口号if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)) == -1){perror("bind error");return -1;}struct sockaddr_in cin;socklen_t addrlen = sizeof(cin);//定义一个文件描述符集合fd_set readfds,tempfds;//将集合清空FD_ZERO(&readfds);//将检测的文件描述符放入集合FD_SET(0,&readfds);FD_SET(sfd,&readfds);int maxfd = sfd;while(1){//将readfds备份tempfds = readfds;int res = select(maxfd+1,&tempfds,NULL,NULL,NULL);if(res == -1){perror("select error");return -1;}else if(res == 0){printf("time out\n");return -1;}link.cin = cin;//数据的互通if(FD_ISSET(sfd,&tempfds)){recvfrom(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&link.cin,&addrlen);//登录if(msg.type == 'L'){strcpy(link.name,msg.usrName);insert(L,link.name,link.cin);char arr[128] = "";sprintf(arr,"***%s登录成功***",msg.usrName);node_p p1 = L->next;while(p1 != NULL){sendto(sfd,arr,sizeof(arr),0,(struct sockaddr*)&(p1->cin),sizeof(p1->cin));p1 = p1->next;}printf("%s [%s %d]:登录成功\n",link.name,inet_ntoa(link.cin.sin_addr),ntohs(link.cin.sin_port));}//聊天else if(msg.type == 'C'){strcpy(link.name,msg.usrName);char brr[2048] = "";sprintf(brr,"%s:%s",msg.usrName,msg.msgText);node_p p2 = L->next;//循环遍历while(p2 != NULL){if(strcmp(p2->name,msg.usrName) != 0){sendto(sfd,brr,sizeof(brr),0,(struct sockaddr*)&(p2->cin),sizeof(p2->cin));}p2 = p2->next;}printf("%s [%s %d]:chat成功\n",link.name,inet_ntoa(link.cin.sin_addr),ntohs(link.cin.sin_port));}//退出else if(msg.type == 'Q'){strcpy(link.name,msg.usrName);delete(L,link.name);char crr[128] = "";sprintf(crr,"***%s退出聊天***",msg.usrName);node_p p3 = L->next;while(p3 != NULL){sendto(sfd,crr,sizeof(crr),0,(struct sockaddr*)&(p3->cin),sizeof(p3->cin));p3 = p3->next;}printf("%s [%s %d]:退出聊天\n",link.name,inet_ntoa(link.cin.sin_addr),ntohs(link.cin.sin_port));}}//系统发送信息if(FD_ISSET(0,&tempfds)){char sbuf[1024] = "";char buf[512] = "";fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = '\0';sprintf(sbuf,"**system**:%s",buf);node_p p = L->next;while(p != NULL){if(sendto(sfd,sbuf,sizeof(sbuf),0,(struct sockaddr*)&(p->cin),sizeof(p->cin)) == -1){perror("sendto error");return -1;}p = p->next;}printf("**system**[%s %d]:chat成功\n",inet_ntoa(sin.sin_addr),ntohs(sin.sin_port));}}return 0;
}

客户端

#include <myhead.h>struct msgTyp
{char type;  //L  C  Qchar usrName[20];char msgText[1024];
};int main(int argc, const char *argv[])
{struct msgTyp usr;int cfd = socket(AF_INET,SOCK_DGRAM,0);if(cfd == -1){perror("socket error");return -1;}//判断是否写外部参数if(argc < 3){printf("请输入IP和端口号\n");return -1;}//填写服务器信息struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(atoi(argv[2]));sin.sin_addr.s_addr = inet_addr(argv[1]);socklen_t addrlen = sizeof(sin);//输入姓名char name[20] = "";printf("请输入姓名>>>>");fgets(name,sizeof(name),stdin);name[strlen(name)-1] = '\0';usr.type = 'L';strcpy(usr.usrName,name);if(sendto(cfd,&usr,sizeof(usr),0,(struct sockaddr*)&sin,sizeof(sin)) == -1){perror("sendto error");return -1;}//定义一个文件描述符,将检测的文件描述符放入集合fd_set readfds,tempfds;FD_ZERO(&readfds);FD_SET(0,&readfds);FD_SET(cfd,&readfds);int maxfd = cfd;  //记录最大的文件描述符while(1){tempfds = readfds;int res = select(maxfd+1,&tempfds,NULL,NULL,NULL);if(res == -1){perror("select error");return -1;}//收到客户端信息if(FD_ISSET(cfd,&tempfds)){bzero(usr.msgText,sizeof(usr.msgText));if(recvfrom(cfd,usr.msgText,sizeof(usr.msgText)-1,0,(struct sockaddr*)&sin,&addrlen) == -1){perror("recvfrom error");return -1;}printf("%s\n",usr.msgText);}//发送数据if(FD_ISSET(0,&tempfds)){bzero(usr.msgText,sizeof(usr.msgText));fgets(usr.msgText,sizeof(usr.msgText),stdin);usr.msgText[strlen(usr.msgText)-1] = '\0';//退出操作if(strcmp(usr.msgText,"quit") == 0){usr.type = 'Q';sendto(cfd,&usr,sizeof(usr),0,(struct sockaddr*)&sin,addrlen);close(cfd);return 0;}//聊天操作else {usr.type = 'C';if(sendto(cfd,&usr,sizeof(usr),0,(struct sockaddr*)&sin,addrlen) == -1){perror("sendto error");return -1;}}}}return 0;
}

 结果

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

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

相关文章

一、SpringBoot基础搭建

本教程主要给初学SpringBoot的开发者&#xff0c;通过idea搭建单体服务提供手把手教学例程&#xff0c;主要目的在于理解环境的搭建&#xff0c;以及maven模块之间的整合与调用 源码&#xff1a;jun/learn-springboot 以商城项目为搭建例子&#xff0c;首先计划建1个父模块&…

Wireshark TS | DNS 案例分析之外的思考

前言 承接之前一篇《Packet Challenge 之 DNS 案例分析》&#xff0c;在数据包跟踪文件 dnsing.pcapng 中&#xff0c;关于第 4 题&#xff08;What is the largest DNS response time seen in this trace file? &#xff09;的分析过程中曾经碰到一个小问题&#xff0c;主要…

MySQL数据库-MySQL基础-下篇-函数、约束、多表查询、事务

文章目录 函数一、字符串函数练习 二、数值函数三、日期函数四、流程函数总结 约束概述约束演示外键约束概念语法删除/更新行为 总结 多表查询多表关系一对多&#xff08;多对一&#xff09;多对多一对一 多表查询概述内连接外连接自连接*联合查询-union, union all子查询标量子…

一文读懂IP地址

IP地址&#xff08;Internet Protocol Address&#xff09;是指互联网协议地址&#xff0c;是IP协议提供的一种统一的地址格式&#xff0c;它为互联网上的每一个网络和每一台主机分配一个逻辑地址&#xff0c;以此来屏蔽物理地址的差异。IP地址的主要特点是具有唯一性&#xff…

AbstractQueuedSynchronizer 独占式源码阅读

概述 ● 一个int成员变量 state 表示同步状态 ● 通过内置的FIFO队列来完成资源获取线程的排队工作 属性 AbstractQueuedSynchronizer属性 /*** 同步队列的头节点 */private transient volatile Node head;/*** 同步队列尾节点&#xff0c;enq 加入*/private transient …

【XR806开发板试用】使用PWM模块模拟手机呼吸灯提示功能

一般情况下&#xff0c;我们的手机在息屏状态&#xff0c;当收到消息处于未读状态时&#xff0c;会有呼吸灯提醒&#xff0c;这次有幸抽中XR806开发板的试用&#xff0c;经过九牛二虎之力终于将环境搞好了&#xff0c;中间遇到各种问题&#xff0c;在我的另一篇文章中已详细描述…

面试算法-82-不同路径

题目 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&#xff1f; …

MySQL (1)

目录 一、数据库的基本概念 1.1 数据 &#xff08;Data&#xff09; 1.2 表 1.3 数据库 2 数据库管理系统 3 数据库系统 二、数据库发展史 关于第三代数据库 三、关系型数据库 当今主流数据库介绍 关系数据库应用 四、非关系数据库介绍 五、MySQL数据库介绍 MySQL商业…

redis和rabbitmq实现延时队列

redis和rabbitmq实现延时队列 延迟队列使用场景Redis中zset实现延时队列Rabbitmq实现延迟队列 延迟队列使用场景 1. 订单超时处理 延迟队列可以用于处理订单超时问题。当用户下单后&#xff0c;将订单信息放入延迟队列&#xff0c;并设置一定的超时时间。如果在超时时间内用户…

网络编程套接字——实现简单的TCP网络程序

目录 1、TCP socket API详解 socket()&#xff1a; bind()&#xff1a; listen(): accept(): connect(): 2、简易的TCP网络程序 TcpServer.hpp TcpClient.cc Main.cc Log.hpp ThreadPool.hpp Task.hpp Init.hpp Daemon.hpp dict.txt Makefile 1、TCP socket A…

CRM软件推荐2024:五款顶级产品解析,助您找到最佳选项!

一天之计在于晨&#xff0c;一年之计在于春。 2024年&#xff0c;民营经济发展继续壮大&#xff0c;这对于各行各业而言都是一种机遇挑战。企业想要规范化客户管理&#xff0c;实现销售增长&#xff0c;CRM软件仍然是一个不错的选择。在数字化时代&#xff0c;企业数字化转型已…

基于SpringBoot实现WebSocket实时通讯的服务端和客户端

实现功能 服务端注册的客户端的列表&#xff1b;服务端向客户端发送广播消息&#xff1b;服务端向指定客户端发送消息&#xff1b;服务端向多个客户端发送消息&#xff1b;客户端给服务端发送消息&#xff1b; 效果&#xff1a; 环境 jdk&#xff1a;1.8 SpringBoot&#x…

大模型+强化学习_通过强化学习对齐大模型和环境

英文名称: True Knowledge Comes from Practice: Aligning LLMs with Embodied Environments via Reinforcement Learning 中文名称: 实践出真知&#xff1a;通过强化学习将LLMS与具体环境对齐 链接: https://arxiv.org/abs/2401.14151 代码: https://github.com/WeihaoTan/TWO…

BI技巧丨个性化视觉对象

BOSS&#xff1a;那个&#xff0c;那个谁&#xff0c;最近用户反映了&#xff0c;说是你们做的报表不太行啊&#xff1f;&#xff01; 白茶&#xff1a;&#xff08;&#xff1f;&#xff1f;&#xff1f;&#xff09;老板&#xff0c;怎么说&#xff1f; BOSS&#xff1a;就是…

网络原理(5)——IP协议(网络层)

目录 一、IP协议报头介绍 1、4位版本 2、4位首部长度 3、8位服务器类型 4、16位总长度 5、16位标识位 6、3位标志位 7、13位偏移量 8、8位生存空间 9、8位协议 10、16位首部检验和 11、32位源IP地址 12、32位目的IP地址 二、IP协议如何管理地址&#xff1f; 1、动…

Redis入门到实战-第三弹

Redis入门到实战 Redis数据类型官网地址Redis概述Redis数据类型介绍更新计划 Redis数据类型 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://redis.io/Redis概述 Redis是一个开源的&#xff08;采用BSD许可证&#…

《优化接口设计的思路》系列:第九篇—用好缓存,让你的接口速度飞起来

一、前言 大家好&#xff01;我是sum墨&#xff0c;一个一线的底层码农&#xff0c;平时喜欢研究和思考一些技术相关的问题并整理成文&#xff0c;限于本人水平&#xff0c;如果文章和代码有表述不当之处&#xff0c;还请不吝赐教。 作为一名从业已达六年的老码农&#xff0c…

2024Python计算机二级13

一维数据采用线性方式组织&#xff0c;集合不属于线性结构 程调度仅负责对CPU进行分配 快速排序每经过一次元素的交换会产生新的逆序 记住队列中为一个元素的情况 区分二叉树与完全二叉树&#xff0c;前序序列是先访问根节点再访问左子树和右子树&#xff0c;中序序列是访问左子…

《定时执行专家》:Nircmd 的超级搭档,解锁自动化新境界

目录 Nircmd 简介 《定时执行专家》与 Nircmd 的结合 示例&#xff1a; 自动清理电脑垃圾: 定时发送邮件: 定时关闭电脑: 《定时执行专家》的优势: 总结: 以下是一些其他使用示例&#xff1a; 立即下载《定时执行专家》&#xff1a; Nircmd 官方网站&#xff1a; 更…

【数字IC/FPGA】书籍推荐(1)----《轻松成为设计高手--Verilog HDL实用精解》

在下这几年关于数字电路、Verilog、FPGA和IC方面的书前前后后都读了不少&#xff0c;发现了不少好书&#xff0c;也在一些废话书上浪费过时间。接下来会写一系列文章&#xff0c;把一部分读过的书做个测评&#xff0c;根据个人标准按十分制满分来打分分享给大家。 书名&#xf…