基于DUP的网络聊天室

基于UDP的网络聊天室的使用(select)完成的服务器端

#include<head.h>
typedef struct de
{char name[10];struct sockaddr_in cin;struct de* next;
}*linklist;
//创建节点
linklist a_creat()
{linklist p=(linklist)malloc(sizeof(struct de));p->next=NULL;bzero(p->name,sizeof(p->name));return p;
}
//判断是否是新用户上线
linklist panduan(char *buf,struct sockaddr_in cin,linklist head,int sfd)
{linklist p=head;while(p->next!=NULL){if(p->cin.sin_addr.s_addr==cin.sin_addr.s_addr && p->cin.sin_port==cin.sin_port){return head;}p=p->next;}linklist q=a_creat();q->next=head;q->cin=cin;strcpy(q->name,buf);head=q;char sbuf[20]="";strcpy(sbuf,q->name);strcat(sbuf,"上线");printf("%s\n",sbuf);while(q->next!=NULL){q=q->next;sendto(sfd,sbuf,sizeof(sbuf),0,(struct sockaddr*)&(q->cin),sizeof(q->cin));}return head;}
//释放内存,并且删除该节点
linklist free_t(linklist q,linklist head)
{if(q==head){head=q->next;q->next=NULL;free(q);return head;}linklist p=head;while(p->next!=q){p=p->next;}p->next=q->next;q->next=NULL;free(q);return head;}
int main(int argc, const char *argv[])
{//1、创建套接字文件int sfd=socket(AF_INET,SOCK_DGRAM,0);if(sfd==-1){perror("socket error");return -1;}	int reuse=1;if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){perror("setsockopt error");return -1;}printf("端口号快速重用成功\n");//2、绑定//2.1填充地址信息结构体struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(8888);sin.sin_addr.s_addr=inet_addr("192.168.122.22");//2.2绑定工作if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("bind error");return -1;}//3.定义变量存放客户端地址信息结构体struct sockaddr_in cin;socklen_t socklen=sizeof(cin);int newfd = -1;fd_set readfds,tempfds;FD_ZERO(&readfds);FD_SET(0,&readfds);FD_SET(sfd,&readfds);linklist head=a_creat();linklist Mhead=head;while(1){Mhead=head;tempfds=readfds;int res=select(sfd+1,&tempfds,NULL,NULL,NULL);if(res==-1){perror("select error");return -1;}else if(res==0){printf("timeout\n");return -1;}if(FD_ISSET(0,&tempfds))//服务器发送消息{char rbuf[128]="";bzero(rbuf,sizeof(rbuf));scanf("%s",rbuf);printf("发送成功\n");linklist p=head;while(p->next!=NULL){sendto(sfd,rbuf,sizeof(rbuf),0,(struct sockaddr*)&(p->cin),sizeof(p->cin));p=p->next;}if(strcmp(rbuf,"quit")==0){close(sfd);printf("服务器下线\n");return 0;}}if(FD_ISSET(sfd,&tempfds)){char sbuf[128]="";recvfrom(sfd,sbuf,sizeof(sbuf),0,(struct sockaddr*)&cin,&socklen);head=panduan(sbuf,cin,head,sfd);//判断是否是有用户上线if(head==Mhead)//如果头指针没发生改变,说明是链表中的用户发来消息{linklist yy=head;while(yy->next!=NULL){if(yy->cin.sin_addr.s_addr==cin.sin_addr.s_addr && yy->cin.sin_port==cin.sin_port)//找到用户对应的名字,并且将消息转发给其他用户{char dbuf[128]="";strcpy(dbuf,yy->name);if(strcmp(sbuf,"quit")==0)//判断该用户是否下线{strcat(dbuf,"下线");head=free_t(yy,head);linklist ss=head;while(ss->next!=NULL){if(ss!=yy){sendto(sfd,dbuf,sizeof(dbuf),0,(struct sockaddr*)&(ss->cin),sizeof(ss->cin));}ss=ss->next;}break;}strcat(dbuf,":");strcat(dbuf,sbuf);printf("[%d]%s\n",ntohs(yy->cin.sin_port),dbuf);linklist ss=head;while(ss->next!=NULL){if(ss!=yy){sendto(sfd,dbuf,sizeof(dbuf),0,(struct sockaddr*)&(ss->cin),sizeof(ss->cin));}ss=ss->next;}break;}yy=yy->next;}}}}return 0;
}

使用多进程完成的客户端

#include<head.h>
void handle(int arg)
{if(arg==SIGCHLD){while(waitpid(-1,NULL,WNOHANG)>0);}
}
int main(int argc, const char *argv[])
{if(signal(SIGCHLD,handle)==SIG_ERR){perror("signal error");return -1;}int sfd=socket(AF_INET,SOCK_DGRAM,0);if(sfd==-1){perror("socket error");return -1;}	int reuse=1;if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){perror("setsockopt error");return -1;}printf("端口号快速重用成功\n");//填充服务器地址信息结构体struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(8888);sin.sin_addr.s_addr=inet_addr("192.168.122.22");socklen_t socklen=sizeof(sin);char buf[128]="";printf("请输入登录用户名:");scanf("%s",buf);sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));pid_t pid=fork();while(1){if(pid>0){//主进程输入并且发送消息bzero(buf,sizeof(buf));fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1]='\0';sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));if(strcmp(buf,"quit")==0){close(sfd);printf("你已下线\n");return 0;}}else if(pid==0){//子进程接收消bzero(buf,sizeof(buf));recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&socklen);printf("%s\n",buf);}}return 0;
}

结果

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

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

相关文章

【好用的AI工具Kimi Chat】帮助提高面试效率

一、背景 年前裁员潮&#xff0c;不少人离职找工作&#xff0c;以及年后金三银四&#xff0c;也是求职高峰期。如何更高效的复习技术知识&#xff0c;以及特别是横纵向比对有总结性的问题。本文以面试【测试开发】的岗位为例&#xff0c;对面试题进行拓展&#xff0c;让AI帮助…

基于 Spring Boot 支付宝沙箱支付(Java 版本)

基于 Spring Boot 支付宝沙箱支付&#xff08;Java 版本&#xff09; 步骤第一步&#xff1a;使用支付宝账户登录&#xff0c;打开控制台&#xff0c;进入沙箱环境第二步&#xff1a;配置内网穿透账号第三步&#xff1a;引入支付宝 SDK第四步&#xff1a; 配置 SpringBoot第五步…

C++入门学习(十二)字符串类型

上一节&#xff08;C入门学习&#xff08;十一&#xff09;字符型-CSDN博客&#xff09;中我们学到如何表示和使用一个字符串&#xff0c;本篇文章是字符串&#xff08;多个字符&#xff09;。 定义字符串主要有两种方式&#xff1a; 第一种&#xff1a; char str[] "…

【cucumber】cucumber-reporting生成测试报告

原始的cucumber report 比较粗糙 我们可以通过cucumber-reporting 插件对报告进去优化 在pom.xml里面添加cuccumber-reporting 插件 <!-- 根据 cucumber json文件 美化测试报告--><dependency><groupId>net.masterthought</groupId><artifactId>…

经典面试题-死锁

目录 1.什么是死锁&#xff1f; 2.形成死锁的四个必要条件 3.死锁的三种情况 第一种情况&#xff1a; 举例&#xff1a; 举例&#xff1a; 第二种情况&#xff1a;两个线程 两把锁 举例&#xff1a; 第三种情况&#xff1a;N个线程 M把锁 哲学家进餐问题 1.什么是死锁&…

计算机网络学习The next day

在计算机网络first day中&#xff0c;我们了解了计算机网络这个科目要学习什么&#xff0c;因特网的概述&#xff0c;三种信息交换方式等&#xff0c;在今天&#xff0c;我们就来一起学习一下计算机网络的定义和分类&#xff0c;以及计算机网络中常见的几个性能指标。 废话不多…

安装向量数据库milvus可视化工具attu

使用docker安装的命令和简单就一个命令&#xff1a; docker run -p 8000:3000 -e MILVUS_URL{milvus server IP}:19530 zilliz/attu:v2.3.5sunyuhuasunyuhua-HKF-WXX:~/dockercom/milvus$ docker run -p 8000:3000 -e MILVUS_URL127.0.0.1:19530 zilliz/attu:latest yarn run…

安卓Spinner文字看不清

Holo主题安卓13的Spinner文字看不清&#xff0c;明明已经解决了&#xff0c;又忘记了。 spinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {TextView textV…

网络要素服务(WFS)详解

文章目录 1. 概述2. GetCapabilities3. DescribeFeatureType4. GetFeature4.1 Get访问方式4.2 Post访问方式 5. Transaction5.1 Insert5.2 Replace5.3 Update5.4 Delete 6 注意事项 1. 概述 前置文章&#xff1a; 地图服务器GeoServer的安装与配置 GeoServer发布地图服务&#…

【Qt】—— Qt的基本介绍

目录 &#xff08;一&#xff09;什么是Qt &#xff08;二&#xff09; Qt的发展史 &#xff08;三&#xff09;Qt⽀持的平台 &#xff08;四&#xff09; Qt版本 &#xff08;五&#xff09;Qt的优点 &#xff08;六&#xff09;Qt的应⽤场景 &#xff08;七&#xff09…

Java大型企业进销存系统

技术框架&#xff1a; SpringBoot Spring Data Jpa SpringMvc Shiro安全认证 完整权限系统 easyui 有需要的可以联系我。 运行环境&#xff1a; jdk8 IntelliJ IDEA maven 系统介绍&#xff1a; 导航菜单&#xff1a;系统菜单、销售管理、库存管理、统计报表、基础…

PHP Fatal error: Unparenthesized `a ? b : c ? d : e` is not supported.

这个错误是关于三元运算符的错误 这个错误在php8.0以下的版本好像是没问题呢 PHP Fatal error: Unparenthesized a ? b : c ? d : e is not supported. Use either (a ? b : c) ? d : e or a ? b : (c ? d : e) in /cangku/app/common.php on line 57 这个问题是 程…

Ubuntu使用docker-compose安装redis

ubuntu环境搭建专栏&#x1f517;点击跳转 Ubuntu系统环境搭建&#xff08;十三&#xff09;——使用docker-compose安装redis 文章目录 Ubuntu系统环境搭建&#xff08;十三&#xff09;——使用docker-compose安装redis1.搭建文件夹2.docker-compose.yaml配置文件3.redis.co…

跟着我学Python进阶篇:03. 面向对象(下)

往期文章 跟着我学Python基础篇&#xff1a;01.初露端倪 跟着我学Python基础篇&#xff1a;02.数字与字符串编程 跟着我学Python基础篇&#xff1a;03.选择结构 跟着我学Python基础篇&#xff1a;04.循环 跟着我学Python基础篇&#xff1a;05.函数 跟着我学Python基础篇&#…

抓包工具Fidder

介绍 Fiddler是强大的抓包工具&#xff0c;它的原理是以web代理服务器的形式进行工作的&#xff0c;代理地址&#xff1a;127.0.0.1&#xff0c;默认端口号:8888。代理就是在客户端和服务器之间设置一道官咖&#xff0c;客户端将请求数据发送出去之后&#xff0c;代理服务器会…

【Linux】进程的概念 进程状态 进程优先级

Content 一、什么是进程1. 进程的概念2. 进程的描述 - 进程控制块&#xff08;PCB&#xff09;3. Linux下的进程 二、进程状态1. 教科书中的进程状态运行状态阻塞状态挂起状态 2. Linux下的进程状态R&#xff08;running&#xff09;- 运行状态S&#xff08;sleeping) - 睡眠状…

Rust 程序设计语言学习——基础语法

Rust 语言是一种高效、可靠的通用高级语言。其高效不仅限于开发效率&#xff0c;它的执行效率也是令人称赞的&#xff0c;是一种少有的兼顾开发效率和执行效率的语言。 Rust 语言由 Mozilla 开发&#xff0c;最早发布于 2014 年 9 月。Rust 的编译器是在 MIT License 和 Apach…

大模型日报-20240122

清华、小米、华为、 vivo、理想等多机构联合综述&#xff0c;首提个人LLM智能体、划分5级智能水平 https://mp.weixin.qq.com/s/JYB4BzsXhWF8pEUUkvn_GQ 想必这些唤醒词中至少有一个曾被你的嘴发出并成功呼唤出了一个能给你导航、讲笑话、添加日程、设置闹钟、拨打电话的智能个…

ROS学习笔记7——ROS通信机制3(参数服务器)

参数服务器是以参数共享模式实现的&#xff0c;参数服务器在ROS中主要用于实现不同节点之间的数据共享。参数服务器相当于是独立于所有节点的一个公共容器&#xff0c;可以将数据存储在该容器中&#xff0c;被不同的节点调用&#xff0c;当然不同的节点也可以往其中存储数据。参…

mysql 容器化安装(docker)离线和在线

前言&#xff1a;在部署hive或airflow 升级过程中&#xff0c;总需要一个对应的数据库存储元数据&#xff0c;一个轻量级的mysql容器刚刚好。轻量、可快速移植、具有隔离性。 文章目录 1、查看机器版本2、安装 docker3、启动docker 服务4、docker 常用命令docker5、拉取mysql …