reactor(百万并发服务器) - 2

这是连续剧般的文章,请关注,持续更新中...

系列文章:

http://t.csdnimg.cn/Os83Qicon-default.png?t=N7T8http://t.csdnimg.cn/Os83Q这篇文章将我们的reactro转变成http服务器...

HTTP 

HTTP介绍

        HTTP是一个基于TCP通信协议的基础上的应用层协议。接下来我们需要解析HTTP请求消息、根据业务对数据进行处理、封装HTTP响应消息发出去。

HTTP请求消息格式

        客户端发送一个 HTTP 请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成,下图给出了请求报文的一般格式。

HTTP响应消息格式

        HTTP 响应由四个部分组成,分别是:状态行、消息报头、空行和响应正文。

HTTP业务流程

        HTTP请求消息格式里面的URL就是客户端要想的资源,例如这里就是index.html。所以我们需要从浏览器发来的请求中,把url解析出来,这是第一步;解析出来请求的资源后我们需要去查找服务器是否存在该资源,如果有则状态200,如果没有则404Not Found,这是第二步;我们观察到有个Accpet字段,这是浏览器想要获得资源的类型,所以我们响应发回的响应消息里面,要根据请求的资源,填充Content-Type字段,这是第三步;还有一个需要注意的点,Content-Length字段是根据响应正文(请求的资源)的大小来计算的,我们需要计算资源大小并填充Content-Length字段,这是第四步。至此,响应头就组装好了,后面再按照格式加个换行,最后再把资源发过去就行了。

 代码补充

recv_cb修改

int readline(char *allbuf, int idx, char *linebuf) {uint len = strlen(allbuf);for (; idx < len; idx++) {if (allbuf[idx] == '\r' && allbuf[idx + 1] == '\n') {return idx + 2;}else {*(linebuf++) = allbuf[idx];}}return -1;
}int http_request(struct ntyevent *ev) {char line_buffer[1024] = {0};readline(ev->buffer, 0, line_buffer);if (strstr(line_buffer, "GET")) {ev->method = HTTP_METHOD_GET;//uriint i = 0;while (line_buffer[sizeof("GET ") + i] != ' ') i++;line_buffer[sizeof("GET ") + i] = '\0';sprintf(ev->resource, "./%s/%s", HTTP_WEBSERVER_HTML_ROOT, line_buffer + sizeof("GET "));//Content-Typeif (strstr(line_buffer + sizeof("GET "), ".")) {char *type = strchr(line_buffer + sizeof("GET "), '.') + 1;if (strcmp(type, "html") == 0 || strcmp(type, "css") == 0) {sprintf(ev->Content_Type, "text/%s", type);}else if (strcmp(type, "jpg") == 0 || strcmp(type, "png") == 0 || strcmp(type, "ico") == 0) {sprintf(ev->Content_Type, "image/%s", type);}}else {sprintf(ev->Content_Type, "text/html");}}
}int recv_cb(int fd, int events, void *arg) {struct ntyreactor *reactor = (struct ntyreactor *) arg;struct ntyevent *ev = ntyreactor_find_event_idx(reactor, fd);int len = recv(fd, ev->buffer, BUFFER_LENGTH, 0); //nty_event_del(reactor->epfd, ev);if (len > 0) {ev->length = len;ev->buffer[len] = '\0';printf("[socket fd=%d recv]\n%s\n", fd, ev->buffer); //httphttp_request(ev);nty_event_set(ev, fd, send_cb, reactor);nty_event_add(reactor->epfd, EPOLLOUT, ev);}else if (len == 0) {close(ev->fd);}else {close(ev->fd);}return len;
}

send_cb修改

int http_response(struct ntyevent *ev) {if (ev == NULL) return -1;memset(ev->buffer, 0, BUFFER_LENGTH);int filefd = open(ev->resource, O_RDONLY);if (filefd == -1) { // return 404ev->ret_code = 404;ev->length = sprintf(ev->buffer,"HTTP/1.1 404 Not Found\r\n""Content-Type: %s;charset=utf-8\r\n""Content-Length: 83\r\n\r\n""<html><head><title>404 Not Found</title></head><body><H1>404</H1></body></html>\r\n\r\n",ev->Content_Type);}else {struct stat stat_buf;fstat(filefd, &stat_buf);close(filefd);if (S_ISDIR(stat_buf.st_mode)) {ev->ret_code = 404;ev->length = sprintf(ev->buffer,"HTTP/1.1 404 Not Found\r\n""Content-Type: %s;charset=utf-8\r\n""Content-Length: 83\r\n\r\n""<html><head><title>404 Not Found</title></head><body><H1>404</H1></body></html>\r\n\r\n",ev->Content_Type);}else if (S_ISREG(stat_buf.st_mode)) {ev->ret_code = 200;ev->length = sprintf(ev->buffer,"HTTP/1.1 200 OK\r\n""Content-Type: %s;charset=utf-8\r\n""Content-Length: %ld\r\n\r\n",ev->Content_Type, stat_buf.st_size);}}return ev->length;
}int send_cb(int fd, int events, void *arg) {struct ntyreactor *reactor = (struct ntyreactor *) arg;struct ntyevent *ev = ntyreactor_find_event_idx(reactor, fd);http_response(ev);printf("[socket fd=%d count=%d]\n%s", fd, ev->length, ev->buffer);int res_head_len = send(fd, ev->buffer, ev->length, 0);if (res_head_len > 0) {if (ev->ret_code == 200) {int filefd = open(ev->resource, O_RDONLY);struct stat stat_buf;fstat(filefd, &stat_buf);off_t offset = 0;while (offset != stat_buf.st_size) {int n = sendfile(fd, filefd, &offset, (stat_buf.st_size - offset));if (n == -1 && errno == EAGAIN) {usleep(5000);continue;}}printf("[resource: %s count:%ld]\r\n", ev->resource, offset);close(filefd);}nty_event_del(reactor->epfd, ev);nty_event_set(ev, fd, recv_cb, reactor);nty_event_add(reactor->epfd, EPOLLIN, ev);}else {nty_event_del(reactor->epfd, ev);close(ev->fd);}return 0;
}

sendfile

        有时候我们发送的资源可能是图片、文本等,所以我们需要提供这样的方法。

int filefd = open(ev->resource, O_RDONLY);
struct stat stat_buf;
fstat(filefd, &stat_buf);
off_t offset = 0;
while (offset != stat_buf.st_size) {int n = sendfile(fd, filefd, &offset, (stat_buf.st_size - offset));if (n == -1 && errno == EAGAIN) {usleep(5000);continue;}
}
printf("[resource: %s count:%ld]\r\n", ev->resource, offset);
close(filefd);

完整代码 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/sendfile.h>#define BUFFER_LENGTH           4096
#define MAX_EPOLL_EVENTS        1024
#define SERVER_PORT             8080
#define PORT_COUNT              100
#define HTTP_METHOD_GET        0
#define HTTP_METHOD_POST    1
#define HTTP_WEBSERVER_HTML_ROOT    "html"typedef int (*NCALLBACK)(int, int, void *);struct ntyevent {int fd;int events;void *arg;NCALLBACK callback;int status;char buffer[BUFFER_LENGTH];int length;//http paramint method; //char resource[BUFFER_LENGTH];int ret_code;char Content_Type[512];
};
struct eventblock {struct eventblock *next;struct ntyevent *events;
};struct ntyreactor {int epfd;int blkcnt;struct eventblock *evblk;
};int recv_cb(int fd, int events, void *arg);int send_cb(int fd, int events, void *arg);struct ntyevent *ntyreactor_find_event_idx(struct ntyreactor *reactor, int sockfd);void nty_event_set(struct ntyevent *ev, int fd, NCALLBACK callback, void *arg) {ev->fd = fd;ev->callback = callback;ev->events = 0;ev->arg = arg;
}int nty_event_add(int epfd, int events, struct ntyevent *ev) {struct epoll_event ep_ev = {0, {0}};ep_ev.data.ptr = ev;ep_ev.events = ev->events = events;int op;if (ev->status == 1) {op = EPOLL_CTL_MOD;}else {op = EPOLL_CTL_ADD;ev->status = 1;}if (epoll_ctl(epfd, op, ev->fd, &ep_ev) < 0) {printf("event add failed [fd=%d], events[%d]\n", ev->fd, events);return -1;}return 0;
}int nty_event_del(int epfd, struct ntyevent *ev) {struct epoll_event ep_ev = {0, {0}};if (ev->status != 1) {return -1;}ep_ev.data.ptr = ev;ev->status = 0;epoll_ctl(epfd, EPOLL_CTL_DEL, ev->fd, &ep_ev);return 0;
}int readline(char *allbuf, int idx, char *linebuf) {uint len = strlen(allbuf);for (; idx < len; idx++) {if (allbuf[idx] == '\r' && allbuf[idx + 1] == '\n') {return idx + 2;}else {*(linebuf++) = allbuf[idx];}}return -1;
}int http_request(struct ntyevent *ev) {char line_buffer[1024] = {0};readline(ev->buffer, 0, line_buffer);if (strstr(line_buffer, "GET")) {ev->method = HTTP_METHOD_GET;//uriint i = 0;while (line_buffer[sizeof("GET ") + i] != ' ') i++;line_buffer[sizeof("GET ") + i] = '\0';sprintf(ev->resource, "./%s/%s", HTTP_WEBSERVER_HTML_ROOT, line_buffer + sizeof("GET "));//Content-Typeif (strstr(line_buffer + sizeof("GET "), ".")) {char *type = strchr(line_buffer + sizeof("GET "), '.') + 1;if (strcmp(type, "html") == 0 || strcmp(type, "css") == 0) {sprintf(ev->Content_Type, "text/%s", type);}else if (strcmp(type, "jpg") == 0 || strcmp(type, "png") == 0 || strcmp(type, "ico") == 0) {sprintf(ev->Content_Type, "image/%s", type);}}else {sprintf(ev->Content_Type, "text/html");}}
}int recv_cb(int fd, int events, void *arg) {struct ntyreactor *reactor = (struct ntyreactor *) arg;struct ntyevent *ev = ntyreactor_find_event_idx(reactor, fd);int len = recv(fd, ev->buffer, BUFFER_LENGTH, 0); //nty_event_del(reactor->epfd, ev);if (len > 0) {ev->length = len;ev->buffer[len] = '\0';printf("[socket fd=%d recv]\n%s\n", fd, ev->buffer); //httphttp_request(ev);nty_event_set(ev, fd, send_cb, reactor);nty_event_add(reactor->epfd, EPOLLOUT, ev);}else if (len == 0) {close(ev->fd);}else {close(ev->fd);}return len;
}int http_response(struct ntyevent *ev) {if (ev == NULL) return -1;memset(ev->buffer, 0, BUFFER_LENGTH);int filefd = open(ev->resource, O_RDONLY);if (filefd == -1) { // return 404ev->ret_code = 404;ev->length = sprintf(ev->buffer,"HTTP/1.1 404 Not Found\r\n""Content-Type: %s;charset=utf-8\r\n""Content-Length: 83\r\n\r\n""<html><head><title>404 Not Found</title></head><body><H1>404</H1></body></html>\r\n\r\n",ev->Content_Type);}else {struct stat stat_buf;fstat(filefd, &stat_buf);close(filefd);if (S_ISDIR(stat_buf.st_mode)) {ev->ret_code = 404;ev->length = sprintf(ev->buffer,"HTTP/1.1 404 Not Found\r\n""Content-Type: %s;charset=utf-8\r\n""Content-Length: 83\r\n\r\n""<html><head><title>404 Not Found</title></head><body><H1>404</H1></body></html>\r\n\r\n",ev->Content_Type);}else if (S_ISREG(stat_buf.st_mode)) {ev->ret_code = 200;ev->length = sprintf(ev->buffer,"HTTP/1.1 200 OK\r\n""Content-Type: %s;charset=utf-8\r\n""Content-Length: %ld\r\n\r\n",ev->Content_Type, stat_buf.st_size);}}return ev->length;
}int send_cb(int fd, int events, void *arg) {struct ntyreactor *reactor = (struct ntyreactor *) arg;struct ntyevent *ev = ntyreactor_find_event_idx(reactor, fd);http_response(ev);printf("[socket fd=%d count=%d]\n%s", fd, ev->length, ev->buffer);int res_head_len = send(fd, ev->buffer, ev->length, 0);if (res_head_len > 0) {if (ev->ret_code == 200) {int filefd = open(ev->resource, O_RDONLY);struct stat stat_buf;fstat(filefd, &stat_buf);off_t offset = 0;while (offset != stat_buf.st_size) {int n = sendfile(fd, filefd, &offset, (stat_buf.st_size - offset));if (n == -1 && errno == EAGAIN) {usleep(5000);continue;}}printf("[resource: %s count:%ld]\r\n", ev->resource, offset);close(filefd);}nty_event_del(reactor->epfd, ev);nty_event_set(ev, fd, recv_cb, reactor);nty_event_add(reactor->epfd, EPOLLIN, ev);}else {nty_event_del(reactor->epfd, ev);close(ev->fd);}return 0;
}int accept_cb(int fd, int events, void *arg) {//非阻塞struct ntyreactor *reactor = (struct ntyreactor *) arg;if (reactor == NULL) return -1;struct sockaddr_in client_addr;socklen_t len = sizeof(client_addr);int clientfd;if ((clientfd = accept(fd, (struct sockaddr *) &client_addr, &len)) == -1) {printf("accept: %s\n", strerror(errno));return -1;}if ((fcntl(clientfd, F_SETFL, O_NONBLOCK)) < 0) {printf("%s: fcntl nonblocking failed, %d\n", __func__, MAX_EPOLL_EVENTS);return -1;}struct ntyevent *event = ntyreactor_find_event_idx(reactor, clientfd);nty_event_set(event, clientfd, recv_cb, reactor);nty_event_add(reactor->epfd, EPOLLIN, event);printf("new connect [%s:%d], pos[%d]\n",inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), clientfd);return 0;
}int init_sock(short port) {int fd = socket(AF_INET, SOCK_STREAM, 0);fcntl(fd, F_SETFL, O_NONBLOCK);struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = htonl(INADDR_ANY);server_addr.sin_port = htons(port);bind(fd, (struct sockaddr *) &server_addr, sizeof(server_addr));if (listen(fd, 20) < 0) {printf("listen failed : %s\n", strerror(errno));}return fd;
}int ntyreactor_alloc(struct ntyreactor *reactor) {if (reactor == NULL) return -1;if (reactor->evblk == NULL) return -1;struct eventblock *blk = reactor->evblk;while (blk->next != NULL) {blk = blk->next;}struct ntyevent *evs = (struct ntyevent *) malloc((MAX_EPOLL_EVENTS) * sizeof(struct ntyevent));if (evs == NULL) {printf("ntyreactor_alloc ntyevents failed\n");return -2;}memset(evs, 0, (MAX_EPOLL_EVENTS) * sizeof(struct ntyevent));struct eventblock *block = (struct eventblock *) malloc(sizeof(struct eventblock));if (block == NULL) {printf("ntyreactor_alloc eventblock failed\n");return -2;}memset(block, 0, sizeof(struct eventblock));block->events = evs;block->next = NULL;blk->next = block;reactor->blkcnt++; //return 0;
}struct ntyevent *ntyreactor_find_event_idx(struct ntyreactor *reactor, int sockfd) {int blkidx = sockfd / MAX_EPOLL_EVENTS;while (blkidx >= reactor->blkcnt) {ntyreactor_alloc(reactor);}int i = 0;struct eventblock *blk = reactor->evblk;while (i++ < blkidx && blk != NULL) {blk = blk->next;}return &blk->events[sockfd % MAX_EPOLL_EVENTS];
}int ntyreactor_init(struct ntyreactor *reactor) {if (reactor == NULL) return -1;memset(reactor, 0, sizeof(struct ntyreactor));reactor->epfd = epoll_create(1);if (reactor->epfd <= 0) {printf("create epfd in %s err %s\n", __func__, strerror(errno));return -2;}struct ntyevent *evs = (struct ntyevent *) malloc((MAX_EPOLL_EVENTS) * sizeof(struct ntyevent));if (evs == NULL) {printf("ntyreactor_alloc ntyevents failed\n");return -2;}memset(evs, 0, (MAX_EPOLL_EVENTS) * sizeof(struct ntyevent));struct eventblock *block = (struct eventblock *) malloc(sizeof(struct eventblock));if (block == NULL) {printf("ntyreactor_alloc eventblock failed\n");return -2;}memset(block, 0, sizeof(struct eventblock));block->events = evs;block->next = NULL;reactor->evblk = block;reactor->blkcnt = 1;return 0;
}int ntyreactor_destory(struct ntyreactor *reactor) {close(reactor->epfd);//free(reactor->events);struct eventblock *blk = reactor->evblk;struct eventblock *blk_next = NULL;while (blk != NULL) {blk_next = blk->next;free(blk->events);free(blk);blk = blk_next;}return 0;
}int ntyreactor_addlistener(struct ntyreactor *reactor, int sockfd, NCALLBACK acceptor) {if (reactor == NULL) return -1;if (reactor->evblk == NULL) return -1;struct ntyevent *event = ntyreactor_find_event_idx(reactor, sockfd);nty_event_set(event, sockfd, acceptor, reactor);nty_event_add(reactor->epfd, EPOLLIN, event);return 0;
}int ntyreactor_run(struct ntyreactor *reactor) {if (reactor == NULL) return -1;if (reactor->epfd < 0) return -1;if (reactor->evblk == NULL) return -1;struct epoll_event events[MAX_EPOLL_EVENTS + 1];int i;while (1) {int nready = epoll_wait(reactor->epfd, events, MAX_EPOLL_EVENTS, 1000);if (nready < 0) {printf("epoll_wait error, exit\n");continue;}for (i = 0; i < nready; i++) {struct ntyevent *ev = (struct ntyevent *) events[i].data.ptr;if ((events[i].events & EPOLLIN) && (ev->events & EPOLLIN)) {ev->callback(ev->fd, events[i].events, ev->arg);}if ((events[i].events & EPOLLOUT) && (ev->events & EPOLLOUT)) {ev->callback(ev->fd, events[i].events, ev->arg);}}}return 0;
}int main(int argc, char *argv[]) {unsigned short port = SERVER_PORT;if (argc == 2) {port = atoi(argv[1]);}struct ntyreactor *reactor = (struct ntyreactor *) malloc(sizeof(struct ntyreactor));ntyreactor_init(reactor);int i;int sockfds[PORT_COUNT] = {0};for (i = 0; i < PORT_COUNT; i++) {sockfds[i] = init_sock(port + i);ntyreactor_addlistener(reactor, sockfds[i], accept_cb);}ntyreactor_run(reactor);ntyreactor_destory(reactor);for (i = 0; i < PORT_COUNT; i++) {close(sockfds[i]);}free(reactor);return 0;
}

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

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

相关文章

【2024最新】PE工具箱【下载安装】零基础到大神【附下载链接】

下载链接&#xff1a;点这里 1.PE (Portable Executable) 工具箱通常用于处理Windows可执行文件和动态链接库&#xff08;DLL&#xff09;的二进制文件格式。这些工具对于进行逆向工程、软件分析和系统维护等任务非常有用。以下是PE工具箱的一些常见功能和用法&#xff1a; 查…

VR博物馆:让博物馆传播转化为品牌影响力

随着VR技术的不断进步&#xff0c;VR全景技术已经成为了文化展示和传播的一项重要工具&#xff0c;相较于传统视频、图文等展现方式&#xff0c;VR全景体验更加直观、便捷&#xff0c;其中蕴涵的信息量也更加丰富&#xff0c;这也为公众了解博物馆和历史文化带来了更为深刻的体…

洗衣洗鞋柜洗衣洗鞋小程序

支持&#xff1a;一键投递、上门取衣、自主送店、多种支付方式 TEL: 17638103951(同V) -----------------用户下单-------------- -------------------------多种支付和投递方式------------------------- -----------------商家取鞋--------------

Transformer的最简洁pytorch实现

目录 前言 1. 数据预处理 2. 模型参数 3. Positional Encoding 4. Pad Mask 5. Subsequence Mask 6. ScaledDotProductAttention 7. MultiHeadAttention 8. FeedForward Networks 9. Encoder Layer 10. Encoder 11. Decoder Layer 12. Decoder 13. Transformer 1…

基于STM32HAL库看门狗(独立看门狗)-简述

目录 概述 一、开发环境 二、STM32CubeMx配置 三、编码 四、运行结果 五、总结 概述 一个成熟靠谱的项目&#xff0c;离不开“看门狗”的必选项&#xff0c;凡是人写的程序多少都会有出现bug的情况&#xff08;或芯片外设受外界干扰导致故障程序卡死、跑飞的情况&#xf…

AI:58-基于深度学习的猫狗图像识别

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌在这个漫长的过程,中途遇到了不少问题,但是…

【LeetCode】每日一题 2023_11_5 重复的DNA序列

文章目录 刷题前唠嗑重复的DNA序列题目描述代码和解题思路偷看大佬题解结语 刷题前唠嗑 LeetCode? 启动&#xff01;&#xff01;&#xff01; 重复的DNA序列 题目链接&#xff1a;187. 重复的DNA序列 题目描述 代码和解题思路 func findRepeatedDnaSequences(s string) …

基于SpringBoot+Vue的旅游系统、前后端分离

博主24h在线&#xff0c;想要源码文档部署视频直接私聊&#xff0c;低价有偿&#xff01; 基于SpringBootVue的旅游系统、前后端分离 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI 工具&#xff1a;IDEA/Eci…

使用脚手架创建项目,使用组件开发

单文件组件 单文件组件就是一个文件对应一个组件, 单文件组件的名字通常是xxx.vue(命名规范和组件名的命名规范相同),这个文件是Vue框架规定的只有它能够认识&#xff0c;浏览器无法直接打开运行 Vue框架可以将xxx.vue文件进行编译为浏览器能识别的html js css的代码 xxx.vu…

蒙哥马利算法模乘(四)

一 蒙哥马利算法模乘介绍 蒙哥马利模乘算法主要为了进行大数运算a*b mod n,在介绍蒙哥马利模乘之前,先让我们来了解蒙哥马利约减。 1.1 蒙哥马利约减 a mod n 如果a是一个2048位的整数,n是一个1024位的整数,如果直接采用相除的方式,不论在空间还是时间上都会产生非常大…

Swift 和 Python 两种语言中带关联信息错误(异常)类型的比较

0. 概览 如果我们分别在平静如水、和谐感人的 Swift 和 Python 社区抛出诸如“Python 是天下最好的语言…” 和 “Swift 是宇宙第一语言…”之类的言论会有怎样的“下场”&#xff1f; 我们并不想对可能发生的“炸裂”景象做出什么预测&#xff0c;也无意比较 Swift 与 Pytho…

安吉寻梦桃花原

安吉——西湖边的那片竹海 安吉县&#xff0c;地处浙江西北部&#xff0c;湖州市辖县之一&#xff0c;北靠天目山&#xff0c;面向沪宁杭。建县于公元185年&#xff0c;县名出自《诗经》“安且吉兮”之意。 安吉县生态环境优美宜居&#xff0c;境内“七山一水二分田”&#xf…

Java锁常见面试题

图片引用自&#xff1a;不可不说的Java“锁”事 - 美团技术团队 1 java内存模型 java内存模型(JMM)是线程间通信的控制机制。JMM定义了主内存和线程之间抽象关系。线程之间的共享变量存储在主内存中&#xff0c;每个线程都有一个私有的本地内存&#xff0c;本地内存中存储了该…

AI:59-基于深度学习的行人重识别

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌在这个漫长的过程,中途遇到了不少问题,但是…

SOEM源码解析——ecx_init_context(初始化句柄)

0 工具准备 1.SOEM-master-1.4.0源码1 ecx_init_context函数总览 /*** brief 初始化句柄* param context 句柄*/ void ecx_init_context(ecx_contextt *context) {int lp;*(context->slavecount) 0;/* clean ec_slave array *//* 清空从站信息数组 */memset(context->…

win10设置windows永不更新

以下方法能全部设置都要全部设置。 方法一&#xff1a;Windows设置 要想关闭Win10自动更新&#xff0c;比较简单的一种方法就是进入到Windows设置中&#xff0c;将Windows更新直接关闭。步骤如下&#xff1a; 1、按“Windows I”键&#xff0c;打开Windows设置&#xff0c;再…

服务器数据恢复—Zfs文件系统下文件被误删除的如何恢复数据?

服务器故障&#xff1a; 一台zfs文件系统服务器&#xff0c;管理员误操作删除服务器上的数据。 服务器数据恢复过程&#xff1a; 1、将故障服务器所有磁盘编号后取出&#xff0c;硬件工程师检测所有硬盘后没有发现有磁盘存在硬件故障。以只读方式将全部磁盘做扇区级别的镜像备…

gcc -static 在centos stream8 和centos stream9中运行报错的解决办法

gcc -static 在centos stream8 和centos stream9中运行报错的解决办法&#xff1a; 报/usr/bin/ld: cannot find -lc 我们下载glibc-static&#xff1a; 选择x86_64的。 还有一个是libxcrypt-static&#xff0c;依旧在这个网站里搜。 rpm -ivh glibc-static-2.28-239.el8.x…

使用seldom编写http接口用例

在编写接口用例的过程中&#xff0c;针对一个接口&#xff0c;往往只是参数不同&#xff0c;那么参数化就非常有必要了。 seldom 中参数化的用法非常灵活&#xff0c;这里仅介绍file_data() 的N种玩法。 二维列表 当参数比较简单时可以试试下面的方式。 参数化数据 {"…

onnx 模型加载部署运行方式

1.通过文件路径的onnx模型加载方式: 在onnxruntime下面的主要函数:session Ort::Session(env, w_modelPath.c_str(), sessionOptions); 这里的文件路径是宽字节的&#xff0c;通过onnx文件路径直接加载模型。 在opencv下使用dnn加载onnx模型的主要函数: std::string model…