web服务器的开发(简易版本)

article/2025/10/22 10:30:42

文章目录

    • 总体介绍
        • 使用的知识总结:
        • http协议请求报文格式:
        • http协议响应消息格式:
        • 使用epoll模型作为web服务器:

总体介绍

使用浏览器作为客户端访问web服务器;

使用的知识总结:

  socktet编程:
    socket -> setsockopt -> bind -> listen -> read -> write -> send -> recv -> close ;
  常用网络服务器模型:
    多进程版本;
    多线程版本;
    多路IO复用;
    第三方库libevent;
  TCP/IP四层模型:
     应用层 -> 传输层 -> 网络层 -> 数据链路层
  使用的协议:
    TCP/IP、http协议
  熟悉http协议的请求和应答协议

http协议请求报文格式:

1 请求行  GET /test.txt HTTP/1.1
2 请求行  健值对
3 空行  \r\n
4 数据

在这里插入图片描述

http协议响应消息格式:

1 状态行  200 表示成功, 404 表示请求的资源不存在
2 消息报头 健值对
3 空行 \r\nz
4 响应正文

使用epoll模型作为web服务器:

<webserver.c>

//web服务端程序--使用epoll模型
#include <unistd.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <signal.h>
#include <dirent.h>#include "pub.h"
#include "wrap.h"
//处理客户端请求
int http_request(int cfd, int epfd);int main(){//若web服务器给浏览器发送数据时,浏览器已经关闭连接,//则web服务器会受到SIGPIPE信号,会直接将进程终止,我们将该信号屏蔽struct sigaction act;act.sa_handler = SIG_IGN;sigemptyset(&act.sa_mask);act.sa_flags = 0;sigaction(SIGPIPE, &act, NULL);//改变当前的工作目录,专门设置一个目录作为根目录char path[255] = {0};//getenv是函数名,从环境中取字符串,获取环境变量的值sprintf(path, "%s/%s", getenv("HOME"), "webpath");chdir(path);//创建socket--设置端口复用 -- bind//该函数 是自己写的 在 "wrap.c"中int lfd = tcp4bind(9999, NULL);//设置监听 "wrap.c"Listen(lfd, 128);//创建epoll树int epfd = epoll_create(1024);if(epfd < 0){perror("epoll_create error");close(lfd);return -1;}//将监听文件描述符上树struct epoll_event ev;ev.data.fd = lfd;ev.events = EPOLLIN;epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &ev);int i;int cfd;int sockfd;int nready;struct epoll_event events[1024];while(1){//等待事件发生nready = epoll_wait(epfd, events, 1024, -1);if(nready < 0){if(error == EINTR){//阻塞函数,可以被信号打断, 不应该退出进程continue;}break;}for(i = 0; i < nready; i++){sockfd = events[i].data.fd;//有客户端连接请求if(sockfd == lfd){//接受新的客户端连接 "wrap.c"cfd = Accept(lfd, NULL, NULL);//设置cfd为非阻塞int flags = fcntl(cfd, f_GETFL);flags |= O_NONBLOCK;fcntl(cfd, F_SETFL, flags);//将新的cfd上树ev.data.fd = cfd;ev.events = EPOLLIN;epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev);}else{//有客户端数据发来http_request(sockfd, epfd);}}}
}
int send_header(int cfd, char *code, char *msg, char *fileType, int len){char buf[1024] = {0};sprintf(buf, "HTTP/1.1 %s %s\r\n", code, msg);sprintf(buf + strlen(buf), "Content-Length:%d\r\n", fileType);strcat(buf, "\r\n");Write(cfd, buf, strlen(buf));return 0;}
int send_file(int cfd, char *fileName){//打开文件int fd = open(fileName, O_RDONLY);if(fd < 0){perror("open error");return -1;}int n;char buf[1024];while(1){memset(buf, 0x00, sizeof(buf));n = read(fd, buf, sizeof(buf));if(n <= 0){break;}else{Write(cfd, buf, n);}}return 0;
}
int http_request(int cfd, int epfd){int n;char buf[1024];//读取请求行数据,分析出要请求的资源文件名memset(buf, 0x00, sizeof(buf));//整行读 "wrap.c"n = Readline(cfd, buf, sizeof(buf));if(n <= 0){printf("read error or client closed, n == [%d]\n", n);close(cfd);//将文件描述符下树epoll_ctl(epfd, EPOLL_CTL_DEL, cfd,  NULL);return -1;}printf("buf == [%s]\n", buf);char reqTtpe[16] = {0};char fileName[255] = {0};char protocal[16] = {0};sscanf(buf, "%[^ ] %[^ ] %[^ \r\n]", reqType, fileName, protocal);printf("[%s]\n", fileName);char *pFile = fileName;if(strlen(fileName) <= 1){strcpy(pFile, "./");}else{pFile = fileName + 1;}//转换汉字编码 "pub.c" strdecode(pFile, pFile);printf("[%s]\n",pFile);//循环读取玩剩余的数据,避免产生粘包while((n = Readline(cfd, buf, sizeof(buf)) > 0);//判断问价是否存在struct stat st;if(stat(pFile, &st) < 0){printf("file not exist\n");//发送头部信息send_header(cfd, "404", "NOT FOUND", get_mime_type(".html"), 0);//发送文件内容send_file(cfd, "error.html");}//若文件存在else{//判断文件类型//普通文件if(S_ISREG(st.st_mode)){printf("file exist\n");send_header(cfd, "200", "OK", get_mime_type(pFile), st.st_size);//发送文件内容send_file(pFile);}else if(S_ISDIR(st.st_mode)){printf("目录文件\n");char buffer[1024];//发送文件头部信息send_header(cfd, "200", "OK", get_mime_type(".html"), 0);//发送文件信息,如果是目录用html文件将该目录中所有文件名 以超链接形式显示在//发送文件头部send_file(cfd, "html/dir_header.html");//文件列表信息 "<dirent.h>"struct dirent **namelist;int num;num = scandir(pFile, &namelist, NULL, alphasort);if(num < 0){perror("scandir error");close(cfd);epoll_ctl(epfd, EPOLL_CTL_DEL, cfd, NULL);return -1;}else{while(num--){printf("%s/n", namelist[num]->d_name);memset(buffer, 0x00, sizeof(buffer));if(namelist[num]->d_type == DT_DIR){sprintf(buffer, "<li><a href= %s/>%s</a></li>", namelist[num]->d_name, namelist[num]->d_name);}else{sprintf(buffer, "<li><a href = %s>%s</a></li>", namelist[num]->d_name, namelist[num]->d_name);}free(namelist[num]);// "wrap.c"Write(cfd, buffer, sizeof(buffer));}free(namelist);}send_file(cfd, "html/dir_tail.html");}}	return 0;
}

<wrap.h>

#ifndef __WRAP_H_
#define __WRAP_H_
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <strings.h>void perr_exit(const char *s);
int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);
int Bind(int fd, const struct sockaddr *sa, socklen_t salen);
int Connect(int fd, const struct sockaddr *sa, socklen_t salen);
int Listen(int fd, int backlog);
int Socket(int family, int type, int protocol);
ssize_t Read(int fd, void *ptr, size_t nbytes);
ssize_t Write(int fd, const void *ptr, size_t nbytes);
int Close(int fd);
ssize_t Readn(int fd, void *vptr, size_t n);
ssize_t Writen(int fd, const void *vptr, size_t n);
ssize_t my_read(int fd, char *ptr);
ssize_t Readline(int fd, void *vptr, size_t maxlen);
int tcp4bind(short port,const char *IP);
#endif

“wrap.c”

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <strings.h>
//绑定错误显示和退出
void perr_exit(const char *s)
{perror(s);exit(-1);
}int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
{int n;again:if ((n = accept(fd, sa, salenptr)) < 0) {if ((errno == ECONNABORTED) || (errno == EINTR))//ECONNABORTED 代表连接失败 ETINTR 代表被信号打断goto again;elseperr_exit("accept error");}return n;
}int Bind(int fd, const struct sockaddr *sa, socklen_t salen)
{int n;if ((n = bind(fd, sa, salen)) < 0)perr_exit("bind error");return n;
}int Connect(int fd, const struct sockaddr *sa, socklen_t salen)
{int n;if ((n = connect(fd, sa, salen)) < 0)perr_exit("connect error");return n;
}int Listen(int fd, int backlog)
{int n;if ((n = listen(fd, backlog)) < 0)perr_exit("listen error");return n;
}int Socket(int family, int type, int protocol)
{int n;if ((n = socket(family, type, protocol)) < 0)perr_exit("socket error");return n;
}ssize_t Read(int fd, void *ptr, size_t nbytes)
{ssize_t n;again:if ( (n = read(fd, ptr, nbytes)) == -1) {if (errno == EINTR)//被信号打断应该继续读goto again;elsereturn -1;}return n;
}ssize_t Write(int fd, const void *ptr, size_t nbytes)
{ssize_t n;again:if ( (n = write(fd, ptr, nbytes)) == -1) {if (errno == EINTR)goto again;elsereturn -1;}return n;
}int Close(int fd)
{int n;if ((n = close(fd)) == -1)perr_exit("close error");return n;
}/*参三: 应该读取的字节数*/
ssize_t Readn(int fd, void *vptr, size_t n)
{size_t  nleft;              //usigned int 剩余未读取的字节数ssize_t nread;              //int 实际读到的字节数char   *ptr;ptr = vptr;nleft = n;while (nleft > 0) {if ((nread = read(fd, ptr, nleft)) < 0) {if (errno == EINTR)nread = 0;elsereturn -1;} else if (nread == 0)break;nleft -= nread;//防止一次数据没有读完ptr += nread;//指针需要向后移动}return n - nleft;
}ssize_t Writen(int fd, const void *vptr, size_t n)
{size_t nleft;ssize_t nwritten;const char *ptr;ptr = vptr;nleft = n;while (nleft > 0) {if ( (nwritten = write(fd, ptr, nleft)) <= 0) {if (nwritten < 0 && errno == EINTR)nwritten = 0;elsereturn -1;}nleft -= nwritten;ptr += nwritten;}return n;
}static ssize_t my_read(int fd, char *ptr)
{static int read_cnt;static char *read_ptr;static char read_buf[100];//定义了100的缓冲区if (read_cnt <= 0) {
again://使用缓冲区可以避免多次从底层缓冲读取数据--为了提高效率if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {if (errno == EINTR)goto again;return -1;} else if (read_cnt == 0)return 0;read_ptr = read_buf;}read_cnt--;*ptr = *read_ptr++;//从缓冲区取数据return 1;
}
//读取一行
ssize_t Readline(int fd, void *vptr, size_t maxlen)
{ssize_t n, rc;char    c, *ptr;ptr = vptr;for (n = 1; n < maxlen; n++) {if ( (rc = my_read(fd, &c)) == 1) {*ptr++ = c;if (c  == '\n')//代表任务完成break;} else if (rc == 0) {//对端关闭*ptr = 0;//0 = '\0'return n - 1;} elsereturn -1;}*ptr  = 0;return n;
}int tcp4bind(short port,const char *IP)
{struct sockaddr_in serv_addr;int lfd = Socket(AF_INET,SOCK_STREAM,0);bzero(&serv_addr,sizeof(serv_addr));//清空serv_addr地址 对比 memset()if(IP == NULL){//如果这样使用 0.0.0.0,任意ip将可以连接serv_addr.sin_addr.s_addr = INADDR_ANY;}else{if(inet_pton(AF_INET,IP,&serv_addr.sin_addr.s_addr) <= 0){perror(IP);//转换失败exit(1);}}serv_addr.sin_family = AF_INET;serv_addr.sin_port   = htons(port);int opt = 1;setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));Bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));return lfd;
}

“pub.c”

//该函数主要处理文件类型,以及返回HTTP文件类型格式

#include "pub.h"
//通过文件名字获得文件类型
char *get_mime_type(char *name)
{char* dot;dot = strrchr(name, '.');	//自右向左查找‘.’字符;如不存在返回NULL/**charset=iso-8859-1	西欧的编码,说明网站采用的编码是英文;*charset=gb2312		说明网站采用的编码是简体中文;*charset=utf-8			代表世界通用的语言编码;*						可以用到中文、韩文、日文等世界上所有语言编码上*charset=euc-kr		说明网站采用的编码是韩文;*charset=big5			说明网站采用的编码是繁体中文;**以下是依据传递进来的文件名,使用后缀判断是何种文件类型*将对应的文件类型按照http定义的关键字发送回去*/if (dot == (char*)0)return "text/plain; charset=utf-8";if (strcmp(dot, ".html") == 0 || strcmp(dot, ".htm") == 0)return "text/html; charset=utf-8";if (strcmp(dot, ".jpg") == 0 || strcmp(dot, ".jpeg") == 0)return "image/jpeg";if (strcmp(dot, ".gif") == 0)return "image/gif";if (strcmp(dot, ".png") == 0)return "image/png";if (strcmp(dot, ".css") == 0)return "text/css";if (strcmp(dot, ".au") == 0)return "audio/basic";if (strcmp( dot, ".wav") == 0)return "audio/wav";if (strcmp(dot, ".avi") == 0)return "video/x-msvideo";if (strcmp(dot, ".mov") == 0 || strcmp(dot, ".qt") == 0)return "video/quicktime";if (strcmp(dot, ".mpeg") == 0 || strcmp(dot, ".mpe") == 0)return "video/mpeg";if (strcmp(dot, ".vrml") == 0 || strcmp(dot, ".wrl") == 0)return "model/vrml";if (strcmp(dot, ".midi") == 0 || strcmp(dot, ".mid") == 0)return "audio/midi";if (strcmp(dot, ".mp3") == 0)return "audio/mpeg";if (strcmp(dot, ".ogg") == 0)return "application/ogg";if (strcmp(dot, ".pac") == 0)return "application/x-ns-proxy-autoconfig";return "text/plain; charset=utf-8";
}
/**********************************************************************/
/* Get a line from a socket, whether the line ends in a newline,* carriage return, or a CRLF combination.  Terminates the string read* with a null character.  If no newline indicator is found before the* end of the buffer, the string is terminated with a null.  If any of* the above three line terminators is read, the last character of the* string will be a linefeed and the string will be terminated with a* null character.* Parameters: the socket descriptor*             the buffer to save the data in*             the size of the buffer* Returns: the number of bytes stored (excluding null) */
/**********************************************************************/
//获得一行数据,每行以\r\n作为结束标记
int get_line(int sock, char *buf, int size)
{int i = 0;char c = '\0';int n;while ((i < size - 1) && (c != '\n')){n = recv(sock, &c, 1, 0);/* DEBUG printf("%02X\n", c); */if (n > 0){if (c == '\r'){n = recv(sock, &c, 1, MSG_PEEK);//MSG_PEEK 从缓冲区读数据,但是数据不从缓冲区清除/* DEBUG printf("%02X\n", c); */if ((n > 0) && (c == '\n'))recv(sock, &c, 1, 0);elsec = '\n';}buf[i] = c;i++;}elsec = '\n';}buf[i] = '\0';return(i);
}//下面的函数第二天使用
/** 这里的内容是处理%20之类的东西!是"解码"过程。* %20 URL编码中的‘ ’(space)* %21 '!' %22 '"' %23 '#' %24 '$'* %25 '%' %26 '&' %27 ''' %28 '('......* 相关知识html中的‘ ’(space)是&nbsp*/
void strdecode(char *to, char *from)
{for ( ; *from != '\0'; ++to, ++from) {if (from[0] == '%' && isxdigit(from[1]) && isxdigit(from[2])) { //依次判断from中 %20 三个字符*to = hexit(from[1])*16 + hexit(from[2]);//字符串E8变成了真正的16进制的E8from += 2;                      //移过已经处理的两个字符(%21指针指向1),表达式3的++from还会再向后移一个字符} else*to = *from;}*to = '\0';
}//16进制数转化为10进制, return 0不会出现
int hexit(char c)
{if (c >= '0' && c <= '9')return c - '0';if (c >= 'a' && c <= 'f')return c - 'a' + 10;if (c >= 'A' && c <= 'F')return c - 'A' + 10;return 0;
}//"编码",用作回写浏览器的时候,将除字母数字及/_.-~以外的字符转义后回写。
//strencode(encoded_name, sizeof(encoded_name), name);
void strencode(char* to, size_t tosize, const char* from)
{int tolen;for (tolen = 0; *from != '\0' && tolen + 4 < tosize; ++from) {if (isalnum(*from) || strchr("/_.-~", *from) != (char*)0) {*to = *from;++to;++tolen;} else {sprintf(to, "%%%02x", (int) *from & 0xff);to += 3;tolen += 3;}}*to = '\0';
}

“pub.h”

#ifndef _PUB_H
#define _PUB_H
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <strings.h>
#include <ctype.h>
char *get_mime_type(char *name);
int get_line(int sock, char *buf, int size);
int hexit(char c);//16进制转10进制
void strencode(char* to, size_t tosize, const char* from);//编码
void strdecode(char *to, char *from);//解码
#endif

效果

在这里插入图片描述
在进程工作目录下webpath 的文件
在这里插入图片描述

点击任意一个超链接都可以跳转到该 文件/目录 获取该文件的内容
在这里插入图片描述
在这里插入图片描述
后台DEBUG的结果
在这里插入图片描述

缺点

该小项目是我跟着视频做的,目前还有一些问题有待完善。
1.该程序在linux中运行,windows中 好像不可以。
2.该程序好像只能从根目录开始,才能完全好使,如果直接输入:192.168.64.129/html 不是从根目录开始,超链接现在还不好使,文件路径不对,不能打开文件,产生404 NO FOUND 错误。
3. 该进程现在只能在虚拟机中,用本机访问,不能用另外一台机器访问。
4. 博主水平有限,仅仅是跟着视频学习,对于如何让web服务器被互联网其他用户访问到,对于这一点,博主一点也不知道,希望有懂的各位,在评论或私信博主,让博主多了解一点知识,不胜感激。

如果有任何问题或者疑问,欢迎在评论区或者指出错误,共同学习

附录

网络编程部分整体回顾:
1 协议的概念
2 OSI7层模型: 物数网传会表应
3 TCP/IP四层模型: 应用层 传输层 网络层 数据链路层
4 几种常见的协议格式, TCP UDP ARP IP
5 socket API编程:
网络字节序 主机字节序
字节序常用到的函数: htons htonl ntohs ntohl
IP地址转换函数: inet_pton inet_ntop
INADDR_ANY
socket API常用的函数:
socket bind listen accept connect read | recv send|write close setsockopt
编写简单版本的服务端程序和客户端程序的流程:

5 三次握手和四次挥手 滑动窗口
TCP 状态转换图
半关闭: close和shutdown的区别
心跳包
同步和异步
阻塞和非阻塞
6 高并发服务器模型:
多进程版本
多线程版本
多路IO复用技术: select poll epoll (ET LT 边缘非阻塞模式)
epoll反应堆
线程池
UDP通信
本地socket通信
第三方库: libevent
事件驱动, 和epoll反应堆一样
普通事件
bufferevent
连接监听器
7 web服务端开发:
html语法
http协议: 请求消息格式 响应消息格式
web服务端开发流程:
libevent作为web服务框架的流程


http://chatgpt.dhexx.cn/article/meHf2PJq.shtml

相关文章

C++ web server服务器 开发

本文是牛客网Linux 高并发服务器开发视频教程的笔记 1、预备知识 1.1 Linux与远程 使用ssh在widows中控制Linux系统&#xff0c;使用vscode控制代码 使用g编译 1.1 静态库与动态库 静态库与动态库的制作、区别 1.2 makefile makefile文件操作就是指定所有源文件的编译顺序…

Web 服务器的搭建

1.下载Nginx源码&#xff1a; wget http://nginx.org/download/nginx-1.19.4.tar.gz2.解压Nginx源码&#xff1a; tar -zxvf nginx-1.19.4.tar.gz 3.安装相关依赖 sudo apt-get install openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev –y4. 进入到nginx-1.19.4目录…

Tomcat服务器和Web开发介绍

Tomcat服务器和Web开发介绍 一、开启Web开发 什么是web开发 WEB&#xff0c;即网页的意思&#xff0c;它用于表示Internet主机上供外界访问的资源。 Internet上供外界访问的Web资源分为&#xff1a; 静态web资源&#xff08;如html 页面&#xff09;&#xff1a;指web页面中供…

C#开发自己的Web服务器

下载源代码 介绍 我们将学习如何写一个简单的web服务器&#xff0c;用于响应知名的HTTP请求&#xff08;GET和POST)&#xff0c;用C#发送响应。然后&#xff0c;我们从网络访问这台服务器&#xff0c;这次我们会说“Hello world!” 背景 HTTP协议 HTTP是服务器和客户机之间的通…

Web开发介绍

Web开发介绍 1 什么是web开发 Web&#xff1a;全球广域网&#xff0c;也称为万维网(www World Wide Web)&#xff0c;能够通过浏览器访问的网站。 所以Web开发说白了&#xff0c;就是开发网站的&#xff0c;例如下图所示的网站&#xff1a;淘宝&#xff0c;京东等等 那么我们…

搭建web服务器

1.要求搭建web服务器&#xff0c;能够访问到网页内容为“小胖&#xff0c;你咋这么胖呢&#xff01;” 2.要求搭建web服务器&#xff0c;创建基于域名的虚拟主机&#xff0c;能够使用www.xiaopang.com和www.dapang.com访问各自的网站网站存放路径分别为/xiaopang和/dapang,内容…

Web开发及服务器

转载自https://www.cnblogs.com/xdp-gacl/p/3729033.html。 一、基本概念 1.1、WEB开发的相关知识 WEB&#xff0c;在英语中web即表示网页的意思&#xff0c;它用于表示Internet主机上供外界访问的资源。 Internet上供外界访问的Web资源分为&#xff1a; 静态web资源&#x…

EI数据库免费检索入口

转载自&#xff1a;http://www.ei-istp.com/New_691.html 具体查询方式&#xff0c;详看链接。

数据库搜索与索引

索引是对数据库表中一列或多列的值进行排序的一种结构&#xff0c;使用索引可快速访问数据库表中的特定信息。如果想按特定职员的姓来查找他或她&#xff0c;则与在表中搜索所有的行相比&#xff0c;索引有助于更快地获取信息。 索引的一个主要目的就是加快检索表中数据&#x…

数据库 索引

多数数据库&#xff0c;使用 B 树&#xff08;Balance Tree&#xff09;的结构来保存索引。 B 树&#xff0c; 最上层节点&#xff1a;根节点 最下层节点&#xff1a;叶子节点 两者之间的节点&#xff1a;中间节点 B 树&#xff0c;显著特征&#xff1a;从根节点&#xff0c;到…

mysql全库搜索关键字_数据库 全文检索

一、概述 MySQL全文检索是利用查询关键字和查询列内容之间的相关度进行检索,可以利用全文索引来提高匹配的速度。 二、语法 MATCH (col1,col2,...) AGAINST (expr [search_modifier]) search_modifier: { IN BOOLEAN MODE | WITH QUERY EXPANSION } 例如:SELECT * FROM tab_n…

人文社科类文献去哪些数据库检索下载

查找下载人文社科类文献的数据库大盘点&#xff1a; 1、文献党下载器&#xff08;wxdown.org&#xff09; 大型文献馆&#xff0c;几乎整合汇集了所有中外文献数据库资源&#xff0c;可附带权限进入文献数据库查找下载文献&#xff0c;覆盖全科包括查找下载人文社科类文献的众…

数据库索引的实现原理

强烈建议参阅链接:http://www.linezing.com/blog/?p=798#nav-1 说白了,索引问题就是一个查找问题。。。 数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。 在数据之外,数据库系统还维护着满足…

WoS数据库使用及检索示例

目录 快速了解一个领域的情况 1. 核心合集检索和所有数据库检索的区别 2. 检索结果分析 2.1 排序方式&#xff08;日期&#xff0c;被引频次&#xff09; 2.2 分析检索结果 2.3 精炼检索结果&#xff08;二次检索&#xff09; 2.4 创建引文报告 2.5 具体某一篇文献 快…

【MySQL】检索数据

每日鸡汤 &#xff1a; —— 若你困于无风之地&#xff0c;我将奏响高空之歌 要和我一起花 10 min 学一会 SQL 嘛&#xff1f; - 当然愿意&#xff0c;我美丽的小姐 &#xff08;封寝期间练就的自言自语能力越来越炉火纯青了~~~&#xff09; 前言&#xff1a; 本实验中所用数据…

数据库的检索(select)

今天我们学习一下数据库检索语句&#xff0c;由于经常用到&#xff0c;有需求的小伙伴欢迎来查看哦&#xff01; 一、简单的查询 --获取所以列 select * from T_table --获取部分列 select id, title from T_table 效果展示&#xff1a; 在...之间&#xff1a;Between.. a…

《MySQL必知必会》学习笔记之“数据库的检索”

文章目录 第一章 SQL与MySQL1 数据库基础2 什么是SQL3 客户机—服务器软件4 MySQL工具mysql命令行实用程序&#xff08;使用最多的实用程序之一&#xff09;MySQL AdministratorMySQL Query Browser 第二章 使用MySQL1 连接2选择数据库3了解数据库和表4 注释 第三章 检索数据1 …

最全最易理解的数据库查询教程

数据库查询 检索数据表中一个字段的内容检索数据表中多个字段的内容检索数据表中所有字段的内容带限制条件的查询表达式查询使用 WHERE 语句和逻辑表达式使用WHERE语句检索单范围数据使用WHERE语句检索双范围数据使用WHERE语句检索不匹配某条件的语句使用通配符[]模糊匹配数据内…

数据库基础知识——SELECT 语句(检索数据)

SQL使用 SQL&#xff08;发音为字母S-Q-L或sequel&#xff09;是结构化查询语言&#xff08;Structured Query Language&#xff09;的缩写。SQL是一种专门用来与数据库通信的语言。 SQL 语言特点&#xff1a; SQL 语言不区分大小写&#xff1b;在命令行窗口的 SQL 语句要以…

Python爬虫获取数据保存到数据库中(超级详细,保证一看就会)

1.简介介绍 -网络爬虫&#xff08;又称为网页蜘蛛&#xff0c;网络机器人&#xff0c;在FOAF社区中间&#xff0c;更经常的称为网页追逐者&#xff09;&#xff0c;是一种按照一定的规则&#xff0c;自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动…