httpserver 下载服务器demo 以及libevent版本的 httpserver

实现效果如下:

图片可以直接显示 

cpp h 这些可以直接显示 其他的 则是提示是否要下载

单线程 还有bug

代码如下  先放上来 

#include "httpserver.h"
#include "stdio.h"
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <dirent.h>#define BURSIZE 1024
int hex2dec(char c)
{if ('0' <= c && c <= '9') {return c - '0';} else if ('a' <= c && c <= 'f') {return c - 'a' + 10;} else if ('A' <= c && c <= 'F') {return c - 'A' + 10;} else {return -1;}
}char dec2hex(short int c)
{if (0 <= c && c <= 9) {return c + '0';} else if (10 <= c && c <= 15) {return c + 'A' - 10;} else {return -1;}
}/** 编码一个url*/
void urlencode(char url[])
{int i = 0;int len = strlen(url);int res_len = 0;char res[BURSIZE];for (i = 0; i < len; ++i) {char c = url[i];if (('0' <= c && c <= '9') ||('a' <= c && c <= 'z') ||('A' <= c && c <= 'Z') || c == '/' || c == '.') {res[res_len++] = c;} else {int j = (short int)c;if (j < 0)j += 256;int i1, i0;i1 = j / 16;i0 = j - i1 * 16;res[res_len++] = '%';res[res_len++] = dec2hex(i1);res[res_len++] = dec2hex(i0);}}res[res_len] = '\0';strcpy(url, res);
}/** 解码url*/
void urldecode(char url[])
{int i = 0;int len = strlen(url);int res_len = 0;char res[BURSIZE];for (i = 0; i < len; ++i) {char c = url[i];if (c != '%') {res[res_len++] = c;} else {char c1 = url[++i];char c0 = url[++i];int num = 0;num = hex2dec(c1) * 16 + hex2dec(c0);res[res_len++] = num;}}res[res_len] = '\0';strcpy(url, res);
}int CreateSocketFD()
{int fd = 0;fd = socket(AF_INET,SOCK_STREAM,0);if(fd == -1){perror("Scoket fd = -1");return 0;}int reuseport = 1;int ret = setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&reuseport,sizeof(reuseport));if(ret == -1){perror("setsocketopt failed");return -1;}struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(8888);addr.sin_addr.s_addr = INADDR_ANY;ret = bind(fd,(struct sockaddr*)&addr,sizeof(addr));if(ret == -1){perror("bind error");return -1;}ret = listen(fd,10);if(ret == -1){perror("listen error ");return -1;}return fd;
}int AcceptClients(int epoll_fd,int fd)
{struct sockaddr addr;int cfd = accept(fd,NULL,NULL);if(cfd == -1){perror("accept failed");}int flag = fcntl(cfd,F_GETFL);flag |= O_NONBLOCK;fcntl(cfd,F_SETFL,flag);struct epoll_event ev;ev.data.fd = cfd;ev.events = EPOLLIN|EPOLLET;int ret = epoll_ctl(epoll_fd,EPOLL_CTL_ADD,cfd,&ev);if(ret == -1){perror("epoll ctl failed");return 0;}return 0;
}const char *GetFileType(const char *filename)
{const char *dot = strrchr(filename,'.');if(dot == NULL){return "text/plain; charset=utf-8";}if(strcmp(dot,".jpg") == 0 ||strcmp(dot,".jpeg") == 0){return "image/jpg";}if(strcmp(dot,".html") == 0 ||strcmp(dot,".htm") == 0){return "text/html; charset=utf-8";}    if(strcmp(dot,".png") == 0){return "image/png";}    if(strcmp(dot,".bmp") == 0){return "image/bmp";}        if(strcmp(dot,".gif") == 0){return "image/gif";}            if(strcmp(dot,".css") == 0){return "text/css";}           if(strcmp(dot,".mp3") == 0){return "audio/mpeg";}               return "text/plain; charset=utf-8";
}int SendHead(int cfd,int status ,const char *desc,const char *type,int size)
{char buf[4096] = {0};sprintf(buf,"http/1.1 %d %s\r\n",status,desc);sprintf(buf+strlen(buf),"content-type: %s\r\n",type);sprintf(buf+strlen(buf),"content-length: %d\r\n\r\n",size);    printf("SendHead buf[%s]\n",buf);send(cfd,buf,strlen(buf),0);return 0;
}int SendDir(const char *dirname,int cfd)
{char buf[4096] = {0};sprintf(buf,"<html><head><title>%s</title></head><body><table>",dirname);printf("SendDir dirname=[%s]\n",dirname);struct dirent **namelist;int count = scandir(dirname,&namelist,NULL,alphasort);printf("SendDir count=[%d]\n",count);for(int i = 0;i< count;i++){char *name = namelist[i]->d_name;struct stat st;char sub_path[1024]={0};sprintf(sub_path,"%s/%s",dirname,name);stat(sub_path,&st);if(S_ISDIR(st.st_mode)){sprintf(buf+strlen(buf),"<tr><td><a href=\"%s/\">%s</a></td><td>%ld</td></tr>",name,name,st.st_size);}else{sprintf(buf+strlen(buf),"<tr><td><a href=\"%s\">%s</a></td><td>%ld</td></tr>",name,name,st.st_size);}printf("cfd:%d Sendbuf[%s]\n",cfd,buf);send(cfd,buf,strlen(buf),0);memset(buf,0,sizeof(buf));free(namelist[i]);}sprintf(buf,"</table></body></html>");printf("cfd:%d Sendbuf[%s]\n",cfd,buf);send(cfd,buf,strlen(buf),0);free(namelist);return 0;
}int SendFile(const char* filename,int cfd)
{int fd = open(filename,O_RDONLY);if(fd >0){#if 0while(1){char buf[1024];int len = read(fd,buf,sizeof buf);if(len >0){send(cfd,buf,len,0);usleep(10);}else if(len == 0){printf("Read file end\n");break;}else{perror("read error");}}#elseoff_t offset = 0;int file_size = lseek(fd,0,SEEK_END);lseek(fd,0,SEEK_SET);while(offset <file_size){int send_len = sendfile(cfd,fd,&offset,file_size-offset);if(send_len == -1){if(errno == EAGAIN){//perror("sendfile no data send");}else{perror("sendfile ret -1");}}else{printf("Send len:%d\n",send_len);}}#endif}else{perror("open file failed");}close(fd);return 0;
}int ParseReqLine(const char *line,int cfd)
{char method[12];char path[1024];printf("ParseReqLine=[%s]\n",line);int ret = sscanf(line,"%[^ ] %[^ ]",method,path);printf("sscanf ret = %d\n",ret);printf("method=[%s],path=[%s]\n",method,path);urldecode(path);printf("afterdecode path=[%s]\n",path);if(ret ==2 ){}else{printf("Reqest line parse failed\n");return -1;}if(strcasecmp(method,"get") == 0){}else if(strcasecmp(method,"post")==0){}else{return -1;}char *file = NULL;if(strcmp(path,"/") == 0){   file = "./";}else{file = path+1;}struct stat st;ret = stat(file,&st);if(ret == -1){printf("file doest not exist\n");SendHead(cfd,404,"Not found",GetFileType(".html"),-1);SendFile("404.html",cfd);return -1;}if(S_ISDIR(st.st_mode)){printf("Directory\n");SendHead(cfd,200,"OK",GetFileType(".html"),-1);SendDir(file,cfd);}else{printf("File\n");SendHead(cfd,200,"OK",GetFileType(file),st.st_size);SendFile(file,cfd);}return 0;
}int Request(int epoll_fd,int cfd)
{char buffer[4096] = {0};char temp_buf[1024] = {0};int read_len = 0;int total = 0;while((read_len = recv(cfd,temp_buf,sizeof(temp_buf),0))>0){if(total+read_len <sizeof(buffer)){memcpy(buffer+total,temp_buf,read_len);total+=read_len;}}if(read_len == -1 && errno == EAGAIN){//读取数据结束char *p = strstr(buffer,"\r\n");if(p){int len = p - buffer;buffer[len] = 0;ParseReqLine(buffer,cfd);}}else if(read_len == 0){//Client close socketepoll_ctl(epoll_fd,EPOLL_CTL_DEL,cfd,NULL);close(cfd);}else{perror("recv error");}return 0;
}int EPOLL_Run(int server_fd)
{int epoll_fd = epoll_create(10);if(epoll_fd == -1){perror("epoll_create failed");return 0;}struct epoll_event ev;ev.data.fd = server_fd;ev.events = EPOLLIN;int ret = epoll_ctl(epoll_fd,EPOLL_CTL_ADD,server_fd,&ev);if(ret == -1){perror("epoll_ctl failed");return 0;}struct epoll_event events[512];while(true){int nReady = epoll_wait(epoll_fd,events,512,-1);for(int i = 0;i<nReady;i++){int fd = events[i].data.fd;if(fd == server_fd){AcceptClients(epoll_fd,fd);}else{if(events[i].events &EPOLLOUT){//g_writeable = true;printf("客户端可以写数据了");}if(events[i].events &EPOLLIN){Request(epoll_fd,fd);}}}}return epoll_fd;
}
int main()
{printf("Hello world\n");char work_dir[] = "/home/develop/httpserver";//chdir(work_dir);int server_fd = CreateSocketFD();if(server_fd <=0){return 0;}EPOLL_Run(server_fd);close(server_fd);return 0;
}

以上  如果遇到大文件 比如mp3 文件的话  就没办法 预览  试听 下载大文件也有问题  

跟踪发现是SendFile 那里有问题   会返回-1

根据网上的例子 改了一个 基于libevent版本的  不会存在这个问题 

#include "sushi.h"
#include "stdio.h"#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/epoll.h>
#include <signal.h>#include <fcntl.h>
#include <unordered_map>
#include <memory>
#include <vector>#include <arpa/inet.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/sendfile.h>#include <dirent.h>#include <evhttp.h>
#include <event.h>
#include <string.h>
#include "event2/http.h"
#include "event2/event.h"
#include "event2/buffer.h"
#include "event2/bufferevent.h"
#include "event2/bufferevent_compat.h"
#include "event2/http_struct.h"
#include "event2/http_compat.h"
#include "event2/util.h"
#include "event2/listener.h"
#include "event2/thread.h"#define MAX_EVENTS	100	
#define RECVBUFSIZ	20bool g_run_flag = true;void sig_handler(int signo)
{g_run_flag = false;printf("\033[0;31mprogram exit by user cmd !!!!\033[0;39m\n");
}#define BURSIZE 1024
int hex2dec(char c)
{if ('0' <= c && c <= '9') {return c - '0';} else if ('a' <= c && c <= 'f') {return c - 'a' + 10;} else if ('A' <= c && c <= 'F') {return c - 'A' + 10;} else {return -1;}
}char dec2hex(short int c)
{if (0 <= c && c <= 9) {return c + '0';} else if (10 <= c && c <= 15) {return c + 'A' - 10;} else {return -1;}
}/** 编码一个url*/
void urlencode(char url[])
{int i = 0;int len = strlen(url);int res_len = 0;char res[BURSIZE];for (i = 0; i < len; ++i) {char c = url[i];if (('0' <= c && c <= '9') ||('a' <= c && c <= 'z') ||('A' <= c && c <= 'Z') || c == '/' || c == '.') {res[res_len++] = c;} else {int j = (short int)c;if (j < 0)j += 256;int i1, i0;i1 = j / 16;i0 = j - i1 * 16;res[res_len++] = '%';res[res_len++] = dec2hex(i1);res[res_len++] = dec2hex(i0);}}res[res_len] = '\0';strcpy(url, res);
}/** 解码url*/
void urldecode(char url[])
{int i = 0;int len = strlen(url);int res_len = 0;char res[BURSIZE];for (i = 0; i < len; ++i) {char c = url[i];if (c != '%') {res[res_len++] = c;} else {char c1 = url[++i];char c0 = url[++i];int num = 0;num = hex2dec(c1) * 16 + hex2dec(c0);res[res_len++] = num;}}res[res_len] = '\0';strcpy(url, res);
}const char *GetFileType(const char *filename)
{const char *dot = strrchr(filename,'.');if(dot == NULL){return "text/plain; charset=utf-8";}if(strcmp(dot,".jpg") == 0 ||strcmp(dot,".jpeg") == 0){return "image/jpg";}if(strcmp(dot,".html") == 0 ||strcmp(dot,".htm") == 0){return "text/html; charset=utf-8";}    if(strcmp(dot,".png") == 0){return "image/png";}    if(strcmp(dot,".bmp") == 0){return "image/bmp";}        if(strcmp(dot,".gif") == 0){return "image/gif";}            if(strcmp(dot,".css") == 0){return "text/css";}           if(strcmp(dot,".mp3") == 0){return "audio/mpeg";}               return "text/plain; charset=utf-8";
}int SendHead(struct bufferevent *event,int status ,const char *desc,const char *type,int size)
{char buf[4096] = {0};sprintf(buf,"http/1.1 %d %s\r\n",status,desc);sprintf(buf+strlen(buf),"content-type: %s\r\n",type);sprintf(buf+strlen(buf),"content-length: %d\r\n\r\n",size);    printf("SendHead buf[%s]\n",buf);//send(cfd,buf,strlen(buf),0);bufferevent_write(event,buf,strlen(buf));return 0;
}int SendDir(struct bufferevent *event,const char *dirname)
{char buf[4096] = {0};sprintf(buf,"<html><head><title>%s</title></head><body><table>",dirname);printf("SendDir dirname=[%s]\n",dirname);struct dirent **namelist;int count = scandir(dirname,&namelist,NULL,alphasort);printf("SendDir count=[%d]\n",count);for(int i = 0;i< count;i++){char *name = namelist[i]->d_name;struct stat st;char sub_path[1024]={0};sprintf(sub_path,"%s/%s",dirname,name);stat(sub_path,&st);if(S_ISDIR(st.st_mode)){sprintf(buf+strlen(buf),"<tr><td><a href=\"%s/\">%s</a></td><td>%ld</td></tr>",name,name,st.st_size);}else{sprintf(buf+strlen(buf),"<tr><td><a href=\"%s\">%s</a></td><td>%ld</td></tr>",name,name,st.st_size);}//printf("cfd:%d Sendbuf[%s]\n",cfd,buf);//send(cfd,buf,strlen(buf),0);bufferevent_write(event,buf,strlen(buf));    memset(buf,0,sizeof(buf));free(namelist[i]);}sprintf(buf,"</table></body></html>");//printf("cfd:%d Sendbuf[%s]\n",cfd,buf);//send(cfd,buf,strlen(buf),0);bufferevent_write(event,buf,strlen(buf));    	free(namelist);return 0;
}int SendFile(struct bufferevent *event,const char* filename)
{int fd = open(filename,O_RDONLY);if(fd >0){#if 1while(1){char buf[1024];int len = read(fd,buf,sizeof buf);if(len >0){//send(cfd,buf,len,0);bufferevent_write(event,buf,len);    usleep(10);}else if(len == 0){printf("Read file end\n");break;}else{perror("read error");}}#elseoff_t offset = 0;int file_size = lseek(fd,0,SEEK_END);lseek(fd,0,SEEK_SET);while(offset <file_size){int send_len = sendfile(cfd,fd,&offset,file_size-offset);if(send_len == -1){if(errno == EAGAIN){//perror("sendfile no data send");}else{perror("sendfile ret -1");}}else{printf("Send len:%d\n",send_len);}}#endif}else{perror("open file failed");}close(fd);return 0;
}int http_request(struct bufferevent *event,char *path)
{char *file = NULL;if(strcmp(path,"/") == 0){   file = "./";}else{file = path+1;}struct stat st;int ret = stat(file,&st);if(ret == -1){printf("file doest not exist\n");SendHead(event,404,"Not found",GetFileType(".html"),-1);SendFile(event,"404.html");return -1;}if(S_ISDIR(st.st_mode)){printf("Directory\n");SendHead(event,200,"OK",GetFileType(".html"),-1);SendDir(event,file);}else{printf("File\n");SendHead(event,200,"OK",GetFileType(file),st.st_size);SendFile(event,file);}return 0;
}void read_cb(struct bufferevent *event,void *arg)
{char buf[256] = {0};char method[10]= {0},path[256]={0},protocol[10]={0};int ret = bufferevent_read(event,buf,sizeof(buf));if(ret >0){sscanf(buf,"%[^ ] %[^ ] %[^ \r\n]",method,path,protocol);if(strcasecmp(method,"get") == 0){char bufline[256] = {0};write(STDOUT_FILENO,buf,ret);while((ret = bufferevent_read(event,bufline,sizeof(bufline)))>0){write(STDOUT_FILENO,bufline,ret);}http_request(event,path);}}
}void bevent_cb(struct bufferevent *event,short what,void *arg)
{if(what & BEV_EVENT_EOF){printf("client closeed\n");bufferevent_free(event);}else if(what & BEV_EVENT_ERROR){printf("client error\n");bufferevent_free(event);}else if(what & BEV_EVENT_CONNECTED){printf("new client connected\n");}
}void listener_cb(struct evconnlistener *listener,evutil_socket_t fd,struct sockaddr *addr,int socklen,void *arg)
{struct event_base *base = (struct event_base*)arg;struct bufferevent *event=  bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);bufferevent_setcb(event,read_cb,NULL,bevent_cb,base);bufferevent_enable(event,EV_READ|EV_WRITE);
}int main (int argc ,char*argv[])
{signal(SIGINT, sig_handler);signal(SIGTERM, sig_handler);signal(SIGKILL, sig_handler);//Program can not recieve SIGKILL(9) signal so.... this cmd does not make any sense// Ignore broken pipessignal(SIGPIPE, SIG_IGN);char work_dir[256]={0};strcpy(work_dir,getenv("PWD"));printf("dir:%s\n",work_dir);chdir(work_dir);struct event_base *base = event_base_new();struct sockaddr_in server;server.sin_family = AF_INET;server.sin_port = htons(9999);server.sin_addr.s_addr = htonl(INADDR_ANY);struct evconnlistener *listener = evconnlistener_new_bind(base,listener_cb,base,LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE_PORT,-1,(struct sockaddr *)&server,sizeof(server));event_base_dispatch(base);event_base_free(base);evconnlistener_free(listener);printf("Exit normally\n");return 0;
}

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

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

相关文章

QScrollArea样式

简介 QScrollBar垂直滚动条分为sub-line、add-line、add-page、sub-page、up-arrow、down-arrow和handle几个部分。 QScrollBar水平滚动条分为sub-line、add-line、add-page、sub-page、left-arrow、right-arrow和handle几个部分。 部件如下图所示&#xff1a; 样式详…

数据结构与算法(一):概述与复杂度分析

参考引用 Hello 算法 Github 仓库&#xff1a;hello-algo 1. 初识算法 1.1 算法无处不在 1.1.1 二分查找&#xff1a;查阅字典 在字典里&#xff0c;每个汉字都对应一个拼音&#xff0c;而字典是按照拼音字母顺序排列的。假设我们需要查找一个拼音首字母为 r 的字&#xff0…

美妆护肤品商城小程序的作用是什么?

化妆品几乎可以覆盖所有人群&#xff0c;各式各样的品牌及经销商非常多&#xff0c;主要销售模式为门店零售、线上入驻电商平台售卖、批发等&#xff0c;近些年随着电商发展迭代以及消费升级&#xff0c;对品牌或经销商来说&#xff0c;传统经营模式变得低效&#xff0c;每个人…

在word文档里面插入漂亮的伪代码

推荐用texsword.0.8 安装与界面 下载链接&#xff1a;https://sourceforge.net/projects/texsword/ 极为轻便&#xff0c;是Word的一个宏 安装过程也是极为简单&#xff0c;复制解压后的 texsword.dotm 文件到 C:\Users\{YOUR_USER_NAME}\AppData\Roaming\Microsoft\Word\ST…

全排列[中等]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给定一个不含重复数字的数组nums&#xff0c;返回其所有可能的全排列。你可以按任意顺序返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 示例…

【MyBatis-Plus】快速精通Mybatis-plus框架—快速入门

大家在日常开发中应该能发现&#xff0c;单表的CRUD功能代码重复度很高&#xff0c;也没有什么难度。而这部分代码量往往比较大&#xff0c;开发起来比较费时。 因此&#xff0c;目前企业中都会使用一些组件来简化或省略单表的CRUD开发工作。目前在国内使用较多的一个组件就是…

QT商业播放器

QT商业播放器 总体架构图 架构优点&#xff1a;解耦&#xff0c;采用生产者消费者设计模式&#xff0c;各个线程各司其职&#xff0c;通过消息队列高效协作 这个项目是一个基于ijkplayer和ffplayer.c的QT商业播放器, 项目有5部分构成&#xff1a; 前端QT用户界面 后端是集成了…

专题一:双指针【优选算法】

双指针应用场景&#xff1a; 数组划分、数组分块 目录 一、移动0 二、复写0 从后向前 三、快乐数 链表带环 四、盛水最多的容器 单调性双指针 五、有效三角形个数 单调性双指针 六、和为s的两个数字 七、三数之和 细节多 需再练 一、移动0 class Solution { public:void move…

小程序入门笔记(一) 黑马程序员前端微信小程序开发教程

微信小程序基本介绍 小程序和普通网页有以下几点区别&#xff1a; 运行环境&#xff1a;小程序可以在手机的操作系统上直接运行&#xff0c;如微信、支付宝等&#xff1b;而普通网页需要在浏览器中打开才能运行。 开发技术&#xff1a;小程序采用前端技术进行开发&#xff0c;…

Html+Css+Js计算时间差,返回相差的天/时/分/秒(从未来的一个日期时间到当前日期时间的差)。

Html部分 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title><link rel"stylesheet" type"text/css" href"css/index.css" /><script src"js/index.js" t…

仿牛客论坛项目 笔记

文章目录 环境配置bean是什么最终成品功能数据库与缓存一致性整个web系统后端的结构spring mvc相关controller常见的代码写法mybatis相关常识测试、调试相关计网相关component相关注解spring全家桶族谱spring衍生框架 run之后发生了什么什么是spring&#xff0c;spring和bean的…

【计算机组成原理】考研真题攻克与重点知识点剖析 - 第 2 篇:数据的表示和运算

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

开源协作开发者内容平台Vrite

什么是 Vrite &#xff1f; Vrite 是一个开源协作空间&#xff0c;用于创建、管理和部署产品文档、技术博客和知识库。它旨在提供高质量、集成的用户和开发人员体验。 Vrite 具有以下功能&#xff1a; 内置管理仪表板&#xff0c;用于使用看板或列表视图管理内容生产和交付&am…

SpringCloud(二)Docker、Spring AMQP、ElasticSearch

文章目录 DockerDocker与虚拟机Docker架构镜像、容器、镜像托管平台Docker架构Docker实践 Spring AMQP简单使用案例工作队列- WorkQueue发布订阅服务FanoutExchangeDirectExchangeTopicExchange 消息转换器 ElasticSearch倒排索引IK分词器IK分词拓展与停用字典 操作索引库mappi…

Dubbo 融合 Nacos 成为注册中心

Nacos 作为 Dubbo 生态系统中重要的注册中心实现&#xff0c;本文将会介绍如何进行 Dubbo 对接 Nacos 注册中心的工作。 预备工作 请确保后台已经启动 Nacos 服务 快速上手 Dubbo 融合 Nacos 成为注册中心的操作步骤非常简单&#xff0c;大致步骤可分为“增加 Maven 依赖”…

创建vue3工程

一、新建工程目录E:\vue\projectCode\npm-demo用Visual Studio Code 打开目录 二、点击新建文件夹按钮&#xff0c;新建vue3-01-core文件夹 三、右键vue3-01-core文件夹点击在集成终端中打开 四、初始化项目&#xff0c;输入npm init 一直敲回车直到创建成功如下图 npm init 五…

国庆加速度!新增功能点锁定功能,敏捷开发新增估算功能,助力项目快速突破!

大家好&#xff0c;CoCode开发云旗下Co-Project V3.6智能项目管理平台正式发布&#xff0c;平台新增功能点锁定功能、敏捷开发模式新增估算板块和两种估算方式。 功能点锁定功能进一步提高了项目估算的灵活性和准确性&#xff0c;有利于提高项目估算效率&#xff1b;而敏捷开发…

JAVA面经整理(8)

一)为什么要有区&#xff0c;段&#xff0c;页&#xff1f; 1)页是内存和磁盘之间交互的基本单位内存中的值修改之后刷到磁盘的时候还是以页为单位的索引结构给程序员提供了高效的索引实现方式&#xff0c;不过索引信息以及数据记录都是记录在文件上面的&#xff0c;确切来说是…

六、互联网技术——数据存储

文章目录 一、存储系统层次结构二、按照重要性分类三、磁盘阵列RAID三、RAID基础四、磁盘阵列分级五、数据备份与恢复六、容灾与灾难恢复 一、存储系统层次结构 常见的三层存储体系结构如下图所示&#xff0c;分为高速缓冲存储器、主存储器和外存储器。 二、按照重要性分类 …

Android自定义Drawable---灵活多变的矩形背景

Android自定义Drawable—灵活多变的矩形背景 在安卓开发中&#xff0c;我们通常需要为不同的按钮设置不同的背景以实现不同的效果&#xff0c;有时还需要这些按钮根据实际情况进行变化。如果采用编写resource中xml文件的形式&#xff0c;就需要重复定义许多只有微小变动的资源…