嵌入式学习第二十四天--网络 服务器
服务器模型
tcp服务器:
socket
bind
listen
accept
recv/send
close
1.支持多客户端访问
//单循环服务器
socket
bind
listen
while(1)
{
accept
while(1)
{
recv/send
}
}
close
2.支持多客户端同时访问 (并发能力)
并发服务器
socket
bind
listen
while(1)
{
connf = accept
pid_t pid = fork();
if(pid > 0)
{
continue;
}else if (pid == 0)
{
while(1) //负责 与 客户端通信的
{
recv/send
}
}
}
close
2.1进程
socket
bind
listen
while(1)
{
connf = accept
pid_t pid = fork();
//出错处理
if (pid == 0)
{
while(1) //负责 与 客户端通信的
{
recv/send
}
}
}
close
2.2线程
void *handle_client(void *arg)
{
while(1) //子线程中 负责 与 客户端通信的
{
recv/send
}
}
socket
bind
listen
while(1)
{
connf = accept
pthread_create();
//出错处理
}
close
-------------------------------------------------------------------------
三种服务器模型比较
1.单循环服务器
2.并发服务器
进程
线程
1、简单循环服务器
http
web 服务器,apache--》cgi,php,perl,IIS--》asp,NGIX,Nlighty
while(1)
{
newfd = accept();
recv();
close(newfd);
}
特点:可以接入多个客户端的信息。
缺点:数据通信过程短,客户端只能一次有效。
实时性效果差。
2、fork循环服务器===>每次有链接则fork一个子进程为该
链接处理通信过程,父进程继续等待新链接。
while(1)
{
newfd = accept();
pid = fork()
if(pid == 0)
{
///接收数据
}
if(pid < 0)
{
perror("fork");
return -1;
}
waitpid()
}
特点:可以完成多个进程的实时交互,信息的完整性可以保证。
缺点:回收资源不方便,每次fork 占用系统资源多。
可能出现僵尸进程
多线程:
特点:
创建速度快,调度快
缺点:
线程共享进程资源,稳定性,安全性 较差
3.并发的服务器模型 ---更高程度上的并发
IO模型
阻塞IO
非阻塞IO
1、阻塞IO
用的最多。
读阻塞。
写阻塞。
2、非阻塞IO
-1 errno EAGAIN whild(1){read()break;}忙等待
control
cntl
3、IO多路复用
4、信号驱动IO SIGIO ---异步
5, 并行模型 进程,线程
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
功能:修改指定文件的属性信息。
参数:fd 要调整的文件描述符
cmd 要调整的文件属性宏名称
... 可变长的属性值参数。
返回值:成功 不一定,看cmd
失败 -1;
int fcntl(int fd, int cmd, ... /* arg */ );
//驱动:
//1.驱动程序 ---- 驱使硬件工作起来的程序
让灯亮起来
eg:修改文件的非阻塞属性:
int flag ;
flag = fcntl(fd,F_GETFL,0); ///获取fd文件的默认属性到flag变量中。
flag = flag | O_NONBLOCK; ///将变量的值调整并添加非阻塞属性
fcntl(fd,F_SETFL,flag); ///将新属性flag设置到fd对应的文件生效。
以上代码执行后的阻塞IO将变成非阻塞方式。
信号驱动IO
//signal
1.fcntl --- 设置 信号接受者
flags = fcntl(fd,F_GETFL); //获得当前标志
fcntl(fd,F_SETFL,flags|O_ASYNC); //异步通信的标志
//同步 通信
//异步 通信
2.将该程序 和 SIGIO信号关联起来
fcntl(fd,F_SETOWN,pid);
3.设置信号处理函数
signal
owner //所有者
缺点:
处理的数量有限 (超过了1个不好判断了)
/---client1
/
server <--------------->|-----client2
\
\---client3
| --->A
/---client1(子进程/线程)-- | --->B
/ | --->C
server <--------------->|-----client2(子进程/线程)-- | --->D
\ | --->E
\---client3(子进程/线程)-- | --->F
| --->G
stdin //读
stdout //写
stderr //--写出错信息
IO多路服用
多路 --- 多个输入输出
复用 --- 复用同一个进程或线程
select //linux提供实现Io多路复用函数
#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);
功能:
io多路复用函数
参数:
nfds //三个集合中最大的文件描述符 + 1
readfds //关心的 读操作的 文件描述符的集合
writefds //关心的 写操作的 文件描述符的集合
exceptfds //关心的 异常操作的 文件描述符的集合
timeout //
NULL --- select 阻塞操作
timeout --- 设定超时时间 > 0 等 这么长时间
== 0 不阻塞
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
返回值:
成功 表示 就绪的文件描述符的数量
失败 -1 && errno设置
void FD_CLR(int fd, fd_set *set); //clear --- 将fd从 set中清除
int FD_ISSET(int fd, fd_set *set); //判断 set 表中 fd是否就绪
void FD_SET(int fd, fd_set *set); //将fd设置(添加)到set中
void FD_ZERO(fd_set *set); //表示将set表清零
注意:
1. select 函数在监控到 有fd就绪后,
它会把未就绪的fd清除掉,每次需要重新获取
2. 超时一次后,时间的变量值为为0
如果,需要每次都有超时时间,需要每次重新给值
//单循环服务器
//第1路IO fgets --收键盘 --- 打印出来 --- stdin 能不能读?
//第2路IO 读管道数据 -- 修改 --- 发回去 --- 管道 能不能读?
select
1.建一张表
放 要监控 的文件描述符
readfds();
2.添加 要监控的文件描述符 到表中
FD_SET()
3.select
eg:
1. 管道双向通信:
A.c B.c
---------A2B----------------->
<--------B2A-----------------
A.c代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <stdlib.h>
//./a.out fifo_A2B fifo_B2A
int main(int argc, const char *argv[])
{if (argc != 3){printf("Usage: %s <fifo_A2B> <fifo_B2A>\n",argv[0]);return -1;}if(mkfifo(argv[1],0666) < 0 && errno != EEXIST){perror("mkfifo fail");return -1;}if(mkfifo(argv[2],0666) < 0 && errno != EEXIST){perror("mkfifo fail");return -1;}int fd1 = open(argv[1],O_WRONLY);int fd2 = open(argv[2],O_RDONLY);if (fd1 < 0 || fd2 < 0){perror("open fail");return -1;}//1.准备表 fd_set readfds;FD_ZERO(&readfds);//2.添加要监控的 fd2FD_SET(0,&readfds);FD_SET(fd2,&readfds);int nfds = fd2 + 1;int i = 0;char buf[1024];while (1){fd_set backfds = readfds;int ret = select(nfds,&backfds,NULL,NULL,NULL);if (ret < 0){perror("select fail");return -1;}if (ret > 0){for (i = 0; i < nfds; ++i){if (FD_ISSET(i,&backfds)){if (i == 0){printf("> ");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = '\0';write(fd1,buf,strlen(buf)+1);if (strncmp(buf,"quit",4) == 0){printf("1 exit......\n");exit(0);}}else if (i == fd2){printf("c> ");read(fd2,buf,sizeof(buf));printf("%s \n",buf);if (strncmp(buf,"quit",4) == 0){printf("2 exit......\n");exit(0);}}}}}}return 0;
}
B.c代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <stdlib.h>//./a.out fifo_A2B fifo_B2A
int main(int argc, const char *argv[])
{if (argc != 3){printf("Usage: %s <fifo_A2B> <fifo_B2A>\n",argv[0]);return -1;}if(mkfifo(argv[1],0666) < 0 && errno != EEXIST){perror("mkfifo fail");return -1;}if(mkfifo(argv[2],0666) < 0 && errno != EEXIST){perror("mkfifo fail");return -1;}int fd1 = open(argv[1],O_RDONLY);int fd2 = open(argv[2],O_WRONLY);if (fd1 < 0 || fd2 < 0){perror("open fail");return -1;}//1.准备表 fd_set readfds;FD_ZERO(&readfds);//2.添加要监控的 fd2FD_SET(0,&readfds);FD_SET(fd1,&readfds);int nfds = fd1 + 1;int i = 0;char buf[1024];while (1){fd_set backfds = readfds;int ret = select(nfds,&backfds,NULL,NULL,NULL);if (ret < 0){perror("select fail");return -1;}if (ret > 0){for (i = 0; i < nfds; ++i){if (FD_ISSET(i,&backfds)){if (i == 0){printf("> ");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = '\0';write(fd2,buf,strlen(buf)+1);if (strncmp(buf,"quit",4) == 0){printf("1 exit......\n");exit(0);}}else if (i == fd1){printf("c> ");read(fd1,buf,sizeof(buf));printf("%s \n",buf);if (strncmp(buf,"quit",4) == 0){printf("2 exit......\n");exit(0);}}}}}}return 0;
}
相关文章:
嵌入式学习第二十四天--网络 服务器
服务器模型 tcp服务器: socket bind listen accept recv/send close 1.支持多客户端访问 //单循环服务器 socket bind listen while(1) { accept while(1) { recv/send } } close 2.支持多客户端同时访问 (并发能力) 并发服务器 socket bind …...
Uniapp组件 Textarea 字数统计和限制
Uniapp Textarea 字数统计和限制 在 Uniapp 中,可以通过监听 textarea 的 input 事件来实现字数统计功能。以下是一个简单的示例,展示如何在 textarea 的右下角显示输入的字符数。 示例代码 首先,在模板中定义一个 textarea 元素ÿ…...
【Java 面试 八股文】计算机网络篇
操作系统篇 1. 什么是HTTP? HTTP 和 HTTPS 的区别?2. 为什么说HTTPS比HTTP安全? HTTPS是如何保证安全的?3. 如何理解UDP 和 TCP? 区别? 应用场景?3.1 TCP 和 UDP 的特点3.2 适用场景 4. 如何理解TCP/IP协议?5. DNS协议 是什么?说说DNS 完整的查询…...
Webservice创建
Webservice创建 服务端创建 3层架构 service注解(commom模块) serviceimpl(server) 服务端拦截器的编写 客户端拦截器 客户端调用服务端(CXF代理) 客户端调用服务端(动态模式调用&a…...
使用VS Code remote ssh进行远程开发的笔记
本文是在VS Code中使用 remote ssh 进行开发的笔记。 安装插件 打开VS Code,在扩展区找到remote相关插件,安装之。下图中红色框出来的是已经安装了的插件(圆圈处即为Remote Explorer)。 实践 连接服务器 新建连接:…...
C语言每日一练——day_3(快速上手C语言)
引言 针对初学者,每日练习几个题,快速上手C语言。第三天。(会连续更新) 采用在线OJ的形式 什么是在线OJ? 在线判题系统(英语:Online Judge,缩写OJ)是一种在编程竞赛中用…...
Linux基本操作指令4
1、查看Ubuntu的版本 lsb_release -a 2、在 Ubuntu 下安装 OpenGL Library sudo apt-get install libglu1-mesa-dev 3、终止当前运行的进程 Ctrl C//默认情况 Ctrl Shift C//若修改了复制快捷键为CtrlC的情况 4、快速打开终端 CtrlAltT 5、关闭终端 Ctrl Shift W…...
PostgreSQL - Windows PostgreSQL 下载与安装
Windows PostgreSQL 下载与安装 1、PostgreSQL 下载 下载地址:https://www.enterprisedb.com/downloads/postgres-postgresql-downloads 2、PostgreSQL 安装 启动安装程序 -> 点击 【Next】 指定安装路径 -> 点击 【Next】 默认勾选 -> 点击 【Next】 指…...
JVM 的主要组成部分及其作用?
创作内容丰富的干货文章很费心力,感谢点过此文章的读者,点一个关注鼓励一下作者,激励他分享更多的精彩好文,谢谢大家! JVM包含两个子系统和两个组件,两个子系统为Class loader(类装载)、Execution engine(执…...
华为eNSP:配置P2P网络类型
一、什么是P2P网络类型 P2P(Point-to-Point)网络类型 是 OSPF(开放最短路径优先)协议中的一种网络类型,用于描述两个路由器之间直接相连的点对点链路。P2P 网络类型通常用于串行链路(如 PPP 或 HDLC 封装&…...
通过数据集微调LLM后怎么调用
通过数据集微调LLM后怎么调用 1. 导入必要的库 from transformers import AutoTokenizer, AutoModelForCausalLMAutoTokenizer:这是 transformers 库中的一个实用类,它能够根据指定的模型名称或路径自动选择合适的分词器。分词器的主要作用是将输入的文本字符串转换为模型可…...
thinkphp+mysql+cast解决text类型字段的文本型数字排序错误的方法 - 数据库文本字段排序ASC、DESC的失效问题
TP中使用cast order $lists AmdCommonTable::where(..............) ->field(*,CAST(w6 AS UNSIGNED) as sort) ->order(sort, asc) ->select() ->toArray(); 先转换为数字,再order by 效果对比 (1/2) 不ok - 直接order by 某字段 asc - 只能按照文本…...
【Manus资料合集】激活码内测渠道+《Manus Al:Agent应用的ChatGPT时刻》(附资源)
DeepSeek 之后,又一个AI沸腾,冲击的不仅仅是通用大模型。 ——全球首款通用AI Agent的破圈启示录 2025年3月6日凌晨,全球AI圈被一款名为Manus的产品彻底点燃。由Monica团队(隶属中国夜莺科技)推出的“全球首款通用AI…...
C++----红黑树map和set的封装
一、红黑树 1.概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出2倍࿰…...
【报错】微信小程序预览报错”60001“
1.问题描述 我在微信开发者工具写小程序时,使用http://localhost:8080是可以请求成功的,数据全都可以无报错,但是点击【预览】,用手机扫描二维码浏览时,发现前端图片无返回且报错60001(打开开发者模式查看日…...
软考 数据通信基础——信道
信道特性 带宽 在模拟信号里频率的差,表示信道能通过的频率 在数字信号里表示最大传输速率,单位用bit/s 通常用W表示 波特率 即码元速率,码元可看作一个时间周期 码元速率B2W也可写成B1/T 码元种类n和码元信息量个数N存在以下关系 Nl…...
windows 平台如何点击网页上的url ,会打开远程桌面连接服务器
你可以使用自定义协议方案(Protocol Scheme)实现网页上点击URL后自动启动远程桌面连接(mstsc),参考你提供的C代码思路,如下实现: 第一步:注册自定义协议 使用类似openmstsc://协议…...
uni-app开发的App和H5嵌套封装的App,以及原生App有什么区别
uni-app 开发的 App 和 H5 嵌套封装的 App 是两种不同的开发模式,虽然它们都可以实现跨平台开发,但在技术实现、性能、功能支持等方面有显著区别。以下是详细对比: 1. uni-app 开发的 App uni-app 是一个基于 Vue.js 的跨平台开发框架&#…...
Anaconda中虚拟环境安装g++和gcc相同版本
安装torchSDF的时候遇到的,这是g和gcc版本不一致的问题 gcc: fatal error: cannot execute cc1plus: execvp: No such file or directory compilation terminated.查看gcc, g版本 gcc --version | head -n1 g --version | head -n1发现gcc的是anaconda中的&#x…...
Docker数据管理,端口映射与容器互联
1.Docker 数据管理 在生产环境中使用 Docker,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作。 容器中的管理数据主要有两种方式: 数据卷(Data Volumns)&a…...
部署前后端项目
部署项目 liunx 软件安装 软件安装方式 在Linux系统中,安装软件的方式主要有四种,这四种安装方式的特点如下: 建议nginx、MySQL、Redis等等使用docker安装,会很便捷,这里只演示JDK、ngxin手动的安装 安装JDK 上述我…...
从零构建逻辑回归: sklearn 与自定义实现对比
文章目录 理论基础1. 逻辑回归模型2. 损失函数3. 梯度推导(1) 计算 ∂ L ∂ y ^ \frac{\partial L}{\partial \hat{y}} ∂y^∂L(2) 计算 ∂ y ^ ∂ z \frac{\partial \hat{y}}{\partial z} ∂z∂y^(3) 计算 ∂ L ∂ z \frac{\partial L}{\partial z} ∂z∂L(4) 计…...
1256:献给阿尔吉侬的花束--BFS多组输入--memset
1256:献给阿尔吉侬的花束--BFS多组输入--memset 题目 解析代码【结构体】用book标记且计步数的代码[非结构体法] 题目 解析 标准的BFS题目,在多组输入中要做的就是先找到这一组的起点和终点,然后将其传给bfs,在多组输入中最易忘记…...
【JavaEE】SpringBoot快速上手,探秘 Spring Boot,搭建 Java 项目的智慧脚手架
1.Spring Boot介绍 在学习SpringBoot之前, 我们先来认识⼀下Spring ,我们看下Spring官⽅的介绍 可以看到,Spring让Java程序更加快速, 简单和安全。 Spring对于速度、简单性和⽣产⼒的关注使其成为世界上最流⾏的Java框架。 Spring官⽅提供了很多开源的…...
【C】初阶数据结构9 -- 直接插入排序
前面我们学习了数据结构二叉树,接下来我们将开启一个新的章节,那就是在日常生活中经常会用到的排序算法。 所谓排序算法就是给你一堆数据,让你从小到大(或从大到小)的将这些数据排成一个有序的序列(这些数据…...
Lottie与LottieFiles:快速为前端Web开发注入精美动画的利器
目录 Lottie与LottieFiles:快速为前端Web开发注入精美动画的利器 一、Lottie是什么?从GIF到JSON的动画技术演进 1、传统动画臃肿的Gif 2、Lottie的突破性创新 二、Lottie的核心组件解析(Lottie的技术架构) 1、Lottie核心三要…...
Spring boot创建时常用的依赖
新建SpringBoot Maven项目中pom常用依赖配置及常用的依赖的介绍 1.springboot项目的总(父)依赖大全 <parent><artifactId>spring-boot-dependencies</artifactId><groupId>org.springframework.boot</groupId><version>2.3.3.RELEASE<…...
音乐API
https://neteasecloudmusicapi.vercel.app/docs/#/https://neteasecloudmusicapi.vercel.app/docs/#/ 使用实例 所有榜单内容摘要 说明 : 调用此接口,可获取所有榜单内容摘要 接口地址 : /toplist/detail 调用例子 : /toplist/detail 获取歌单所有歌曲 说明 : 由于网易云…...
UML(统一建模语言)详解:从理论到实践
1. UML概述 1.1 定义与历史背景 统一建模语言(Unified Modeling Language, UML) 是一种标准化的可视化建模语言,用于描述、设计、构造和文档化软件系统。它诞生于1994-1997年,由Grady Booch、James Rumbaugh和Ivar Jacobson&…...
C语言练习题--洛谷P5143攀爬者
题目背景 HKE 考完 GDOI 之后跟他的神犇小伙伴们一起去爬山。 题目描述 他在地形图上标记了 N 个点,每个点 Pi 都有一个坐标 (xi,yi,zi)。所有点对中,高度值 z 不会相等。HKE 准备从最低的点爬到最高的点,他的攀爬满足以下条件&am…...
