网络编程 IO多路复用 [select版] (TCP网络聊天室)
//head.h 头文件
//TcpGrpSer.c 服务器端
//TcpGrpUsr.c 客户端
select函数
功能:阻塞函数,让内核去监测集合中的文件描述符是否准备就绪,若准备就绪则解除阻塞。
原型:
#include <sys/select.h>#include <sys/time.h>#include <sys/types.h>#include <unistd.h>int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout); 参数:int nfds:所有集合中最大的文件描述符+1; fd_set *readfds, fd_set *writefds,fd_set *exceptfds:读集合,写集合,其他集合。用不上的集合填NULL;struct timeval *timeout:设置超时时间; 1) 填NULL,不设置超时时间,会一直阻塞直到文件描述符准备就绪,解除阻塞;2) 设置超时时间;struct timeval {long tv_sec; /* seconds */ 秒long tv_usec; /* microseconds */ 微秒}; 返回值:>0, 成功,返回成功触发事件的文件描述符个数;=0, 超时了=-1,函数运行失败,更新errno; 操作集合的函数: void FD_CLR(int fd, fd_set *set); 将指定的fd从集合中删除int FD_ISSET(int fd, fd_set *set); 判断fd是否在集合中,若存在返回真,否则返回假void FD_SET(int fd, fd_set *set); 将fd添加到集合中void FD_ZERO(fd_set *set); 清空
head.h
#ifndef __HEAD_H__
#define __HEAD_H__#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<strings.h>
#include<unistd.h>
#include<math.h>
#include<errno.h>
#include<fcntl.h>
#include<signal.h>#include<sys/stat.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/shm.h>
#include<sys/time.h>
#include<sys/sem.h>#include<pthread.h>
#include<semaphore.h>#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/select.h>
#include<poll.h>#define NUM 10
#define ERR_MSG(msg) do{\printf("line: %d\n",__LINE__);\perror(msg);\
}while(0)
#define PORT 6666 //端口号的网络字节序 1024~49151
#define IP "192.168.250.100" //ifconfig查看本机IP (ipv4)#endif
TcpGrpSer.c
#include "head.h"int main(int argc, const char *argv[])
{//创建流式套接字int sfd = socket(AF_INET,SOCK_STREAM,0);if(sfd<0){ERR_MSG("socket");return -1;}//填充服务器自身的地址信息结构体//真实的地址信息结构体根据地址族制定AF_INET ; man 7 ipstruct sockaddr_in sin; sin.sin_family = AF_INET; //必须填充AF_INETsin.sin_port = htons(PORT); //端口号的网络字节序 1024~49151sin.sin_addr.s_addr = inet_addr(IP); //ifconfig查看本机IPint reuse = 1;if(setsockopt(sfd, SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0) //允许端口快速被重复使用{ERR_MSG("setsockopt");return -1;}//绑定连接if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0){ERR_MSG("bind");return -1;}printf("bind success\n");//设置监听if(listen(sfd,128) < 0){ERR_MSG("listen");return -1;}//创建读集合fd_set readfds,tempfds;//清空集合FD_ZERO(&readfds);FD_ZERO(&tempfds);//将集合监测的文件描述符放入集合FD_SET(0,&readfds);FD_SET(sfd,&readfds);//用顺序表存储文件描述符的端口信息//监测文件描述符是否准备就绪int maxfd = sfd;int s_res = 0;struct sockaddr_in cin;socklen_t len = sizeof(cin);struct sockaddr_in savcin[1024];int newfd = -1;char buf[128]="";ssize_t res = 0;while(1){tempfds = readfds;//备份readfdss_res = select(maxfd+1,&tempfds,NULL,NULL,NULL);if(s_res<0){ERR_MSG("select");return -1;}else if(0 == s_res){printf("超时...\n");break;}//与客户端通信for(int i=0;i<=maxfd;i++){if(!FD_ISSET(i,&tempfds))continue;if(0 == i){printf("触发键盘输入事件\n");int sndfd=-1;res=scanf("%d %s",&sndfd,buf);while(getchar() !=10);if(res!=2){printf("请输入正确数据格式:[fd(4~1023)] string\n"); continue;}//判断文件是否合法if(sndfd<sfd||sndfd>1023||!FD_ISSET(sndfd,&readfds)){printf("sndfd = %d 是非法文件描述符\n",sndfd);continue;}if(send(sndfd,buf,sizeof(buf),0)<0){ERR_MSG("send");}bzero(buf,sizeof(buf));}else if(i == sfd){printf("触发客户端连建事件\n");newfd = accept(sfd,(struct sockaddr *)&cin,&len);if(newfd < 0){perror("accept");return -1;}savcin[newfd]=cin;printf("[%s:%d] 客户端连接成功 newfd = %d __%d__ \n",\inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);//将新生成的newfd添加到readfdsFD_SET(newfd,&readfds);//更新maxfdmaxfd = maxfd > newfd? maxfd:newfd;}else{printf("触发客户端连建事件__%d__\n",__LINE__);bzero(buf,sizeof(buf));//接收数据res = recv(i,buf,sizeof(buf),0);if(res < 0){ERR_MSG("recv");return -1;}else if(0 == res){printf("{%s:%d} sfd = %d,__%d__ 已下线,结束对话\n",\inet_ntoa(savcin[i].sin_addr),ntohs(savcin[i].sin_port),i,__LINE__); close(i);//关闭文件描述符FD_CLR(i,&readfds);/* //更新maxfdint j=maxfd;for(;j<=0;j--){if(FD_ISSET(j,&readfds)) break;}maxfd = j;*///更新maxfdwhile(!FD_ISSET(maxfd,&readfds)&&maxfd-->=0);continue;}printf("{%s:%d} sfd = %d : %s,__%d__\n",\inet_ntoa(savcin[i].sin_addr),ntohs(savcin[i].sin_port),i,buf,__LINE__); //发送数据strcat(buf,"*_*");if(send(i,buf,sizeof(buf),0)<0){ERR_MSG("send");return -1;}printf("发送成功\n");}}}if(close(sfd)<0){ERR_MSG("close");return -1;}return 0;
}
TcpGrpUsr.c
#include "head.h"int main(int argc, const char *argv[])
{//创建流式套接字int sfd = socket(AF_INET,SOCK_STREAM,0);if(sfd<0){ERR_MSG("socket");return -1;}int reuse = 1;if(setsockopt(sfd, SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0) //允许端口快速被重复使用{ERR_MSG("setsockopt");return -1;}//填充服务器自身的地址信息结构体//真实的地址信息结构体根据地址族制定AF_INET ;struct sockaddr_in sin; sin.sin_family = AF_INET; //必须填充AF_INETsin.sin_port = htons(PORT); //端口号的网络字节序 1024~49151sin.sin_addr.s_addr = inet_addr(IP); //ifconfig查看本机IPif(connect(sfd,(struct sockaddr *)&sin,sizeof(sin))<0){perror("connect");return -1;}printf("连接成功\n");//创建集合struct pollfd fds[2];fds[0].fd = 0;fds[0].events = POLLIN;fds[1].fd = sfd;fds[1].events = POLLIN;char buf[128]="";int res=0;while(1){//阻塞方式监测集合res = poll(fds,2,-1);if(res < 0){ERR_MSG("poll");return -1;}else if(0 == res){printf("time out...\n"); //超时break;}//判断0文件描述符是否有POLLIN事件if((fds[0].revents & POLLIN)){fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = 0;if(send(sfd,buf,sizeof(buf),0) < 0){ERR_MSG("send");return -1;}printf("发送成功\n");}//判断sfd文件描述符是否有POLLIN事件if(fds[1].revents & POLLIN){//接收数据bzero(buf,sizeof(buf));res = recv(sfd,buf,sizeof(buf),0);if(res<0){ERR_MSG("recv");return -1;}else if(res == 0){printf("[%s:%d] 服务器下线__%d__ \n",\inet_ntoa(sin.sin_addr),ntohs(sin.sin_port),__LINE__);break;}printf("[%s:%d] cfd = %d : %s__%d__ \n",\inet_ntoa(sin.sin_addr),ntohs(sin.sin_port),sfd,buf,__LINE__);} }if(close(sfd)<0){ERR_MSG("close");return -1;}return 0;
}
相关文章:
网络编程 IO多路复用 [select版] (TCP网络聊天室)
//head.h 头文件 //TcpGrpSer.c 服务器端 //TcpGrpUsr.c 客户端 select函数 功能:阻塞函数,让内核去监测集合中的文件描述符是否准备就绪,若准备就绪则解除阻塞。 原型: #include <sys/select.…...
数学建模学习(7):单目标和多目标规划
优化问题描述 优化 优化算法是指在满足一定条件下,在众多方案中或者参数中最优方案,或者参数值,以使得某个或者多个功能指标达到最优,或使得系统的某些性能指标达到最大值或者最小值 线性规划 线性规划是指目标函数和约束都是线性的情况 [x,fval]linprog(f,A,b,Aeq,Beq,LB,U…...
Element UI如何自定义样式
简介 Element UI是一套非常完善的前端组件库,但是如何个性化定制其中的组件样式呢?今天我们就来聊一聊这个 举例 就拿最常见的按钮el-button来举例,一般来说默认是蓝底白字。效果图如下 可是我们想个性化定制,让他成为粉底红字应…...
protobuf入门实践2
如何在proto中定义一个rpc服务? syntax "proto3"; //声明protobuf的版本package fixbug; //声明了代码所在的包 (对于C来说就是namespace)//下面的选项,表示生成service服务类和rpc方法描述, 默认是不生成的 option cc_generi…...
adb shell使用总结
文章目录 日志记录系统概览adb 使用方式 adb命令日志过滤按照告警等级进行过滤按照tag进行过滤根据告警等级和tag进行联合过滤屏蔽系统和其他App干扰,仅仅关注App自身日志 查看“当前页面”Activity文件传输截屏和录屏安装、卸载App启动activity其他 日志记录系统概…...
UG NX二次开发(C++)-Tag的含义、Tag类型与其他的转换
文章目录 1、前言2、Tag号的含义3、tag_t转换为int3、TaggedObject与Tag转换3.1 TaggedObject定义3.2 TaggedObject获取Tag3.3 根据Tag获取TaggedObject4.Tag与double类型的转换1、前言 在UG NX中,每个对象对应一个tag号,C++中,其类型是tag_t,一般是5位或者6位的int数字,…...
Informer 论文学习笔记
论文:《Informer: Beyond Efficient Transformer for Long Sequence Time-Series Forecasting》 代码:https://github.com/zhouhaoyi/Informer2020 地址:https://arxiv.org/abs/2012.07436v3 特点: 实现时间与空间复杂度为 O ( …...
c语言位段知识详解
本篇文章带来位段相关知识详细讲解! 如果您觉得文章不错,期待你的一键三连哦,你的鼓励是我创作的动力之源,让我们一起加油,一起奔跑,让我们顶峰相见!!! 目录 一.什么是…...
FFmpeg aresample_swr_opts的解析
ffmpeg option的解析 aresample_swr_opts是AVFilterGraph中的option。 static const AVOption filtergraph_options[] {{ "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS,{ .i64 AVFILTER_THREAD_SLICE }, 0, INT_MA…...
CAN学习笔记3:STM32 CAN控制器介绍
STM32 CAN控制器 1 概述 STM32 CAN控制器(bxCAN),支持CAN 2.0A 和 CAN 2.0B Active版本协议。CAN 2.0A 只能处理标准数据帧且扩展帧的内容会识别错误,而CAN 2.0B Active 可以处理标准数据帧和扩展数据帧。 2 bxCAN 特性 波特率…...
软工导论知识框架(二)结构化的需求分析
本章节涉及很多重要图表的制作,如ER图、数据流图、状态转换图、数据字典的书写等,对初学者来说比较生僻,本贴只介绍基础的轮廓,后面会有单独的帖子详解各图表如何绘制。 一.结构化的软件开发方法:结构化的分析、设计、…...
[SQL挖掘机] - 算术函数 - abs
介绍: 当谈到 SQL 中的 abs 函数时,它是一个用于计算数值的绝对值的函数。“abs” 代表 “absolute”(绝对),因此 abs 函数的作用是返回一个给定数值的非负值(即该数值的绝对值)。 abs 函数接受一个参数&a…...
vue拼接html点击事件不生效
vue使用ts,拼接html,点击事件不生效或者报 is not defined 点击事件要用onclick 不是click let data{name:测,id:123} let conHtml <div> "名称:" data.name "<br>" <p class"cursor blue&quo…...
【Spring】Spring之依赖注入源码解析
1 Spring注入方式 1.1 手动注入 xml中定义Bean,程序员手动给某个属性赋值。 set方式注入 <bean name"userService" class"com.firechou.service.UserService"><property name"orderService" ref"orderService"…...
【微软知识】微软相关技术知识分享
微软技术领域 一、微软操作系统: 微软的操作系统主要是 Windows 系列,包括 Windows 10、Windows Server 等。了解 Windows 操作系统的基本使用、配置和故障排除是非常重要的。微软操作系统(Microsoft System)是美国微软开发的Wi…...
12.python设计模式【观察者模式】
内容:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变的时候,所有依赖于它的对象得到通知并被自动更新。观者者模式又称为“发布-订阅”模式。比如天气预报,气象局分发气象数据。 角色: 抽象主题…...
重生之我要学C++第五天
这篇文章主要内容是构造函数的初始化列表以及运算符重载在顺序表中的简单应用,运算符重载实现自定义类型的流插入流提取。希望对大家有所帮助,点赞收藏评论,支持一下吧! 目录 构造函数进阶理解 1.内置类型成员在参数列表中的定义 …...
复习之linux高级存储管理
一、lvm----逻辑卷管理 1.lvm定义 LVM是 Logical Volume Manager(逻辑卷管理)的简写,它是Linux环境下对磁盘分区进行管理的一种机制。 逻辑卷管理器(LogicalVolumeManager)本质上是一个虚拟设备驱动,是在内核中块设备和物理设备…...
HuggingGPT Solving AI Tasks with ChatGPT and its Friends in Hugging Face
总述 HuggingGPT 让LLM发挥向路由器一样的作用,让LLM来选择调用那个专业的模型来执行任务。HuggingGPT搭建LLM和专业AI模型的桥梁。Language is a generic interface for LLMs to connect AI models 四个阶段 Task Planning: 将复杂的任务分解。但是这里…...
java工程重写jar包中class类覆盖问题
结论:直接在程序中复写jar中的类即可 原因:一般我java工程是运行在tomcat容器中,tomcat容易在加载我们工程类和jar包是的优先级为: 我们工程的class 先于 我们工程lib下的jar 重复的类只加载一次,加载我们复写后的类后…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...
数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
