网络编程作业day7

作业项目:基于UDP的聊天室

服务器代码:

#include <myhead.h>//定义客户信息结构体
typedef struct magtye
{char type;            //消息类型char name[100];         //客户姓名char text[1024];  //客户发送聊天信息
}msg_t;//定义结构体存储每个客户端的ip地址和端口号
typedef struct IP_PORT
{struct sockaddr_in cin;//地址信息struct IP_PORT *next;//}*addrlist;void usr_login(int sfd,msg_t msg,addrlist *head,struct sockaddr_in cin);
void usr_chat(int sfd,msg_t msg,addrlist head,struct sockaddr_in cin);
void usr_quit(int sfd,msg_t msg,addrlist *head,struct sockaddr_in cin);int main(int argc, const char *argv[])
{//创建套接字int sfd=-1;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;}//服务器进行绑定//(1)、从终端获取端口号和地址char SER_IP[100];int SER_PORT;printf("请输入服务器ip地址和端口号:");scanf("%s %d",SER_IP,&SER_PORT);getchar();//吸收垃圾字符//(2)、填充服务器地址信息结构体struct sockaddr_in sin;sin.sin_family=AF_INET;           //地址族sin.sin_port=htons(SER_PORT);    //端口号sin.sin_addr.s_addr=inet_addr(SER_IP);  //IP地址      	socklen_t sin_len=sizeof(sin);//(3)、绑定if(bind(sfd,(struct sockaddr*)&sin,sin_len)==-1){perror("bind error");return -1;}//定义客户端网络信息结构体struct sockaddr_in cin;socklen_t cin_len=sizeof(cin);msg_t msg;//定义客户发送消息的机构体变量//创建父子进程处理不同的操作int pid=fork();if(pid==-1){perror("fork error");return -1;}if(pid==0)//字进程实现服务器接收消息类型{addrlist head=NULL;//链表头指针;while(1){memset(&msg,0,sizeof(msg));memset(&cin,0,sizeof(cin));//接收客户端发来的信息,并判断属于哪种消息类型recvfrom(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&cin,&cin_len);switch(msg.type){case 'L':    //该消息类型代表新用户上线{//创建新节点保存新用户的ip地址和端口号				//向其他在线的用户发送新用户上线通知usr_login(sfd,msg,&head,cin);}break;case 'C':   //该消息类型代表一个用户发送消息给其他用户{usr_chat(sfd,msg,head,cin);}break;case 'Q':   //该消息类型代表一个用户下线{usr_quit(sfd,msg,&head,cin);}break;}}}else if(pid>0)//父进程实现服务器对客户端发送消息{strcpy(msg.name,"服务器消息");msg.type='C';while(1){memset(msg.text,0,sizeof(msg.text));fgets(msg.text,sizeof(msg.text),stdin);msg.text[strlen(msg.text)-1]='\0';sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sin_len);if(strcmp(msg.text,"服务器下线")==0){sleep(1);break;}}kill(pid,SIGKILL);//服务器下线杀死子进程}wait(NULL);//关闭套接字close(sfd);return 0;
}
//用户登录操作函数
void usr_login(int sfd,msg_t msg,addrlist *head,struct sockaddr_in cin)
{//1、创建新节点addrlist s=(addrlist)malloc(sizeof(addrlist));s->next=NULL;//存储新用户的ip地址和端口号printf("%s : %d\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));s->cin=cin;s->next=*head;*head=s;//2、遍历链表将新用户上线消息发送给其他在线用户addrlist p=*head;while (p!=NULL){if(p->cin.sin_port!=cin.sin_port){sendto(sfd, &msg, sizeof(msg),0,(struct sockaddr *)&(p->cin), sizeof(p->cin));}p=p->next; //后移}printf("%s:%s\n",msg.name, msg.text);}//用户聊天操作函数
void usr_chat(int sfd,msg_t msg,addrlist head,struct sockaddr_in cin)
{addrlist p=head;while (p!=NULL){if(p->cin.sin_port!=cin.sin_port){sendto(sfd, &msg, sizeof(msg),0,(struct sockaddr *)&(p->cin), sizeof(p->cin));}p=p->next; //后移}}
//用户退出操作函数
void usr_quit(int sfd,msg_t msg,addrlist *head,struct sockaddr_in cin)
{printf("%s:%s\n",msg.name, msg.text);addrlist p=*head;addrlist del=NULL;while (p!=NULL){if(p->cin.sin_port!=cin.sin_port)  //向其他用户发送某个用户下线消息{sendto(sfd, &msg, sizeof(msg),0,(struct sockaddr *)&(p->cin), sizeof(p->cin));del=p;p=p->next;}else{sendto(sfd, &msg, sizeof(msg),0,(struct sockaddr *)&(p->cin), sizeof(p->cin));//向发出下线消息的用户回复消息if (del==NULL) {*head=p->next;} else {del->next=p->next;}free(del);del=NULL;break;}}
}

客户端代码:

#include <myhead.h>//定义客户信息结构体
typedef struct magtye
{char type;            //消息类型char name[100];         //客户姓名char text[1024];  //客户发送聊天信息
}msg_t;int main(int argc, const char *argv[])
{//创建套接字int cfd=-1;cfd=socket(AF_INET, SOCK_DGRAM, 0);if(cfd==-1){perror("socket error");return -1;}//将端口号快速重用int reuse=1;if(setsockopt(cfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){perror("setsockopt error");return -1;}//(1)、从终端获取端口号和地址char SER_IP[100];int SER_PORT;printf("请输入服务器ip地址和端口号:");scanf("%s %d",SER_IP,&SER_PORT);getchar();//吸收垃圾字符//(2)、填充服务器地址信息结构体struct sockaddr_in sin;sin.sin_family=AF_INET;           //地址族sin.sin_port=htons(SER_PORT);    //端口号sin.sin_addr.s_addr=inet_addr(SER_IP);  //IP地址   socklen_t sin_len=sizeof(sin);msg_t msg;//客户端上线发送消息printf("请输入用户名:");fgets(msg.name,sizeof(msg.name),stdin);msg.name[strlen(msg.name)-1] = '\0';strcpy(msg.text,"已上线");msg.type='L';sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sin_len);//创建多进程进行收发消息操作int pid=fork();if(pid==-1){perror("fork error");return -1;}if(pid>0)//父进程进行读取消息{while(1){recvfrom(cfd,&msg,sizeof(msg),0,NULL,NULL);if(strcmp(msg.text,"退出群聊")==0)    //用户自己下线{break;}printf("[%s]: %s\n", msg.name, msg.text);if(strcmp(msg.text,"服务器下线")==0) //服务器让客户端下线{kill(pid,SIGKILL);break;}}}else if(pid==0)//子进程发送消息{while(1){memset(msg.text,0,sizeof(msg.text));fgets(msg.text,sizeof(msg.text),stdin);//在终端获取聊天信息msg.text[strlen(msg.text)-1]='\0';if(strcmp(msg.text, "下线")==0){msg.type='Q';strcpy(msg.text, "退出群聊");}else{msg.type='C';}sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sin_len);if(strcmp(msg.text,"退出群聊")==0){break;}}exit(EXIT_SUCCESS);}//关闭套接字回收子进程资源wait(NULL);   //阻塞回收子进程资源close(cfd);return 0;
}

项目作业-基于udp的聊天室

思维导图:

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

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

相关文章

刷题日记:面试经典 150 题 DAY5

刷题日记&#xff1a;面试经典 150 题 DAY4 125. 验证回文串28. 找出字符串中第一个匹配项的下标151. 反转字符串中的单词6. Z 字形变换68. 文本左右对齐 125. 验证回文串 原题链接 125. 验证回文串 双指针&#xff0c;一前一后&#xff0c;遇到非数字字母跳过即可 class So…

腾讯云哪款服务器最便宜划算?2024腾讯云服务器优惠价格表

腾讯云优惠活动2024新春采购节活动上线&#xff0c;云服务器价格已经出来了&#xff0c;云服务器61元一年起&#xff0c;配置和价格基本上和上个月没什么变化&#xff0c;但是新增了8888元代金券和会员续费优惠&#xff0c;腾讯云百科txybk.com整理腾讯云最新优惠活动云服务器配…

TCP三次握手四次挥手

目录 TCP报文 ☞ 标志位 TCP状态变迁图&#xff1a; 三次握手 为什么要三次握手&#xff1f; 客户端与服务端接口状态 客户端&#xff1a; 服务端&#xff1a; 第一次握手&#xff1a; 第二次握手&#xff1a; 第三次握手&#xff1a; 四次挥手&#xff1a; 四次挥…

火爆全网,软件测试数据库常用 SQL 语句总结,你要的我都有......

前言 直接上干货 数据定义语言(DDL) 主要负责数据库、数据表、视图、键、索引等结构化的操作 常用的语句有&#xff1a;CREATE DATABASE、CREATE TABLE、ALTER TABLE等 字段的常用约束有&#xff1a;PRIMARY KEY、FOREIGN KEY、NOT NULL、UNIQUE、AUTO_INCREMENT、DEFAULT 常…

onnx模型优化利器onnxoptimizer、onnxsim

ONNX性能优化和调试技巧 - 知乎ONNX模型是一种跨平台、跨框架的模型表示格式,允许用户在不同的深度学习框架之间共享模型和数据,从而加速模型开发和部署。然而,在实际应用中,我们通常需要对ONNX模型进行性能优化和调试,以确保其在不同硬件和…https://zhuanlan.zhihu.com/…

PTA L2-011 玩转二叉树

给定一棵二叉树的中序遍历和前序遍历&#xff0c;请你先将树做个镜面反转&#xff0c;再输出反转后的层序遍历的序列。所谓镜面反转&#xff0c;是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。 输入格式&#xff1a; 输入第一行给出一个正整数N&…

CIP通讯介绍(欧姆龙PLC)

什么是CIP CIP通信是Common Industrial Protocl(CIP)的简称&#xff0c;它是一个点到点的面向对象协议&#xff0c;能够实现工业器件&#xff08;传感器&#xff0c;执行器&#xff09;之间的连接&#xff0c;和高等级的控制器之间的连接。目前&#xff0c;有3种网络DeviceNet…

MySQL--优化(索引--索引创建原则)

MySQL–优化&#xff08;索引–索引创建原则&#xff09; 定位慢查询SQL执行计划索引 存储引擎索引底层数据结构聚簇和非聚簇索引索引创建原则索引失效场景 SQL优化经验 一、索引创建原则 我们使用的索引种类&#xff1a; 主键索引唯一索引根据业务创建的索引&#xff08;复…

怎么给视频活码加入时间设置?限时扫码看视频的制作方法

视频二维码是常见的一种二维码类型&#xff0c;很多人会通过这种方式来分享视频内容&#xff0c;可能某些情况下需要对制作的二维码图片加入扫码限制&#xff0c;比如有效期、填写密码、限制预览时间等设置&#xff0c;那么这些需求怎么在生成二维码时实现呢&#xff1f; 对于…

JAVA 用二分法查找数组中是否存在某个值

二分法查找的概念 二分查找也称折半查找&#xff08;Binary Search&#xff09;&#xff0c;它是一种效率较高的查找方法。首先&#xff0c;将表中间位置记录的关键字与查找关键字比较&#xff0c;如果两者相等&#xff0c;则查找成功&#xff1b;否则利用中间位置记录将表分成…

spring-security 项目实战(一)个人健康档案

spring-security 项目实战&#xff08;一&#xff09;个人健康档案 项目说明项目地址框架信息 代码分析配置类解析默认登录页登录接口执行逻辑登录认证成功之后重定向到main页面过程未登录之前访问 /main生成默认登录页点击登录 登录之后访问 /main执行流程清空认证信息 项目来…

低空经济20人|卓翼智能任雪峰:以技术驱动市场,引领无人机细分领域创新

作为国内系留无人机领域的领头羊企业&#xff0c;卓翼智能致力于提供智能无人系统解决方案。本期“低空经济20人”请到卓翼智能CEO任雪峰分享他对系留无人机研发应用的经验以及未来无人机行业生态发展的观点。 如今&#xff0c;无人机的应用场景逐渐广泛&#xff0c;在社会发展…

18个惊艳的可视化大屏(第20辑):物联网场景

实时监控和管理 物联网系统通常涉及大量的传感器、设备和数据&#xff0c;通过将这些数据可视化展示在大屏上&#xff0c;可以实时监控和管理物联网系统的运行状态。这有助于及时发现问题、快速响应&#xff0c;并提高系统的可靠性和稳定性。 数据分析和决策支持 可视化大屏可…

软件测试--性能测试实战篇

软件测试--性能测试实战篇 项目介绍和部署1. 轻商城项目介绍1.1 背景1.2 简介2. 项目功能架构3. 项目技术架构4. 熟悉数据库设计5. 轻商城项目搭建5.1 准备工作5.2 项目搭建步骤性能测试需求分析1. 性能测试需求分析1.1 如何获取有效的需求2. 性能测试点的提取2.1 性能测试点的…

第五十二回 戴宗二取公孙胜 李逵独劈罗真人-飞桨AI框架安装和使用示例

吴用说只有公孙胜可以破法术&#xff0c;于是宋江请戴宗和李逵去蓟州。两人听说公孙胜的师傅罗真人在九宫县二仙山讲经&#xff0c;于是到了二仙山&#xff0c;并在山下找到了公孙胜的家。 两人请公孙胜去帮助打高唐州&#xff0c;公孙胜说听师傅的。罗真人说出家人不管闲事&a…

SpringMVC 中的常用注解和用法

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;JavaEE &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 注解 1. MVC定义2. 注解2.1 RequestMappin…

leetcode:LCR 006. 两数之和 II - 输入有序数组(python3解法)

难度&#xff1a;简单 给定一个已按照 升序排列 的整数数组 numbers &#xff0c;请你从数组中找出两个数满足相加之和等于目标数 target 。 函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 0 开始计数 &#xff0c;所以答案数组应当满足 0 <…

el-dialog封装组件

父页面 <template><div><el-button type"primary" click"visible true">展示弹窗</el-button><!-- 弹窗组件 --><PlayVideo v-if"visible" :visible.syncvisible /></div> </template><sc…

谷粒学院--在线教育实战项目【一】

谷粒学院--在线教育实战项目【一】 一、项目概述1.1.项目来源1.2.功能简介1.3.技术架构 二、Mybatis-Plus概述2.1.简介2.2.特性 三、Mybatis-Plus入门3.1.创建数据库3.2.创建 User 表3.3.初始化一个SpringBoot工程3.4.在Pom文件中引入SpringBoot和Mybatis-Plus相关依赖3.5.第一…

融资项目——OpenFeign的降级与熔断

当一个微服务调用其他微服务时&#xff0c;如果被调用的微服务因各种原因无法在规定时间内提供服务&#xff0c;则可以直接使用本地的服务作为备选&#xff0c;即进行降级熔断。 如之前所提到的微服务为例&#xff1a; 如果希望实现降级熔断&#xff0c;可以在本地创建一个实现…