网络编程作业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的聊天室
思维导图:
相关文章:

网络编程作业day7
作业项目:基于UDP的聊天室 服务器代码: #include <myhead.h>//定义客户信息结构体 typedef struct magtye {char type; //消息类型char name[100]; //客户姓名char text[1024]; //客户发送聊天信息 }msg_t;//定义结构体存储…...
【Vision Pro杀手级应用】3D音乐会/演唱会,非VR视频播放的形式,而是实实在在的明星“全息”形象,在你的面前表演
核心内容形式:体积视频 参考对标案例深度解读: 体积视频,这一全新的内容形式,正在引领我们进入一个前所未有的四维体验时代。它将传统的演艺形式推向了新的高度,让我们能够更加深入地沉浸在虚拟世界中,感受前所未有的视听盛宴。 在这一领域,有一个引人注目的案例,那…...

变频器学习
西门子变频器 SINAMICS V20 入门级变频器 SINAMICS G120C...

Linux Ubuntu系统安装MySQL并实现公网连接本地数据库【内网穿透】
文章目录 前言1 .安装Docker2. 使用Docker拉取MySQL镜像3. 创建并启动MySQL容器4. 本地连接测试4.1 安装MySQL图形化界面工具4.2 使用MySQL Workbench连接测试 5. 公网远程访问本地MySQL5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定TCP地址远程访问 前言 本文主…...
0048__Unix传奇
Unix传奇 (上篇)_unix传奇(上篇)-CSDN博客 Unix传奇 (下篇)-CSDN博客 Unix现状与未来——CSDN对我的采访_nuix邮件系统行业地位-CSDN博客...

蓝桥杯-排序
数组排序 Arrays.sort(int[] a) 这种形式是对一个数组的所有元素进行排序,并且时按从小到大的顺序。 package Work;import java.util.*;public class Imcomplete {public static void main(String args[]) {int arr[]new int [] {1,324,4,5,7,2};Arrays.sort(arr)…...

计算机设计大赛 深度学习的视频多目标跟踪实现
文章目录 1 前言2 先上成果3 多目标跟踪的两种方法3.1 方法13.2 方法2 4 Tracking By Detecting的跟踪过程4.1 存在的问题4.2 基于轨迹预测的跟踪方式 5 训练代码6 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 基于深度学习的视频多目标跟踪实现 …...
高性能JSON框架之FastJson的简单使用
高性能JSON框架之FastJson的简单使用、 1.前言 1.1.FastJson的介绍: JSON协议使用方便,越来越流行,JSON的处理器有很多,这里我介绍一下FastJson,FastJson是阿里的开源框架,被不少企业使用,是一个极其优秀的Json框架,Github地址: FastJson 1.2.FastJson的特点: 1.F…...
★判断素数的几种方法(由易到难,由慢到快)
素数的定义: 素数,又称为质数,指的是“大于1的整数中,只能被1和这个数本身整除的数”。换句话说,素数是只有两个正约数(1和本身)的自然数。素数在数论中有着重要的地位,且素数的个数…...

vue svelte solid 虚拟滚动性能对比
前言 由于svelte solid 两大无虚拟DOM框架,由于其性能好,在前端越来越有影响力。 因此本次想要验证,这三个框架关于实现表格虚拟滚动的性能。 比较版本 vue3.4.21svelte4.2.12solid-js1.8.15 比较代码 这里使用了我的 stk-table-vue(np…...

IDEA中新增文件,弹出框提示是否添加到Git点错了,怎么重新设置?
打开一个配置了Git的项目,新增一个文件,会弹出下面这个框。提示是否将新增的文件交给Git管理。 一般来说,会选择ADD,并勾选Dont ask agin,添加并不再询问。如果不小心点错了,可在IDEA中重新设置(…...
LV15 day5 字符设备驱动读写操作实现
一、读操作实现 ssize_t xxx_read(struct file *filp, char __user *pbuf, size_t count, loff_t *ppos); 完成功能:读取设备产生的数据 参数: filp:指向open产生的struct file类型的对象,表示本次read对应的那次open pbuf&#…...

Uninty 鼠标点击(摄像机发出射线-检测位置)
平面来触发碰撞,胶囊用红色材质方便观察。 脚本挂载到胶囊上方便操作。 目前实现的功能,鼠标左键点击,胶囊就移动到那个位置上。 using System.Collections; using System.Collections.Generic; using UnityEngine;public class c6 : MonoBe…...
描述下Vue自定义指令
描述下Vue自定义指令 (1)自定义指令基本内容(2)使用场景(3)使用案例 在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层…...
2024.3.7
作业: 1、OSI的七层网络模型有哪些,每一层有什么作用? (1)应用层 负责处理不同应用程序之间的通信,需要满足提供的协议,确保数据发送方和接收方的正确 (2)表示层…...
this.$watch 侦听器 和 停止侦听器
使用组件实例的$watch()方法来命令式地创建一个侦听器; 它还允许你提前停止该侦听器 语法:this.$watch(data, method, object) 1. data:侦听的数据源,类型为String 2. method:回调函数&#x…...
P1030 [NOIP2001 普及组] 求先序排列题解
题目 给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不同的大写字母表示,且二叉树的节点个数≤8)。 输入输出格式 输入格式 共两行,均为大写字母组成的字符串,表示一棵二叉树的中序与后序排列。…...
【分布式】NCCL Split Tree kernel内实现情况 - 06
相关系列 【分布式】NCCL部署与测试 - 01 【分布式】入门级NCCL多机并行实践 - 02 【分布式】小白看Ring算法 - 03 【分布式】大模型分布式训练入门与实践 - 04 目录 相关系列概述1.1 Tree1.2 double binary tree初始化和拓扑2.1 Tree的初始化与差异2.2 ncclGetBtreeKernel内部…...
C语言深入学习 --- 4.自定义类型(结构体+枚举+联合)
第四章 自定义类型:结构体,枚举,联合 结构体 结构体类型的声明 结构的自引用 结构体变量的定义和初始化 结构体的内存对齐 结构体实现位段(位段的填充 和 可移植性) 枚举 枚举类型的定义 枚举的优点 枚举的使…...
AI自然语言中默认上下文长度4K 几K是什么意思?
环境: 4K 问题描述: AI自然语言中默认上下文长度4K 几K是什么意思? 解决方案: 在自然语言处理中,“k” 表示 “千”,是一种简写方式。当我们说 “4k” 时,实际上指的是 “4,000”。在上下文…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...