当前位置: 首页 > news >正文

旅游网站开发实训报告seo难不难学

旅游网站开发实训报告,seo难不难学,企业名称自主申报,眼科医院网站做竞价带来的询盘量一、相关知识 1、有限状态机#xff1a; 有限状态机#xff08;Finite State Machine, FSM#xff09;是一种用于描述对象在其生命周期内可能经历的不同状态及其状态转换规则的模型。它广泛应用于游戏开发、网络协议、词法解析、UI逻辑控制等领域。以下是C中有限状态机的简…一、相关知识 1、有限状态机 有限状态机Finite State Machine, FSM是一种用于描述对象在其生命周期内可能经历的不同状态及其状态转换规则的模型。它广泛应用于游戏开发、网络协议、词法解析、UI逻辑控制等领域。以下是C中有限状态机的简介 有限状态机的核心概念 状态State 对象可能处于的某种特定情况如游戏中的角色“空闲”、“移动”、“攻击”。事件Event 触发状态转换的外部或内部条件如用户输入“跳跃”、定时器超时。转换Transition 定义在特定事件发生时从当前状态转移到目标状态的规则如“空闲 → 移动”。动作Action 状态转换时执行的操作如播放动画、发送网络包。 2、http报文 HTTP报文分为请求报文浏览器端向服务器发送和响应报文服务器处理后返回给浏览器端两种每种报文必须按照特有格式生成才能被浏览器端识别。 1请求报文由请求行、请求头部、空行、请求数据四部分组成 请求行用来说明请求类型(方法)、要访问的资源以及使用的http的版本请求头部用来说明服务器要使用的附加信息由“名/值”对组成每对一行中间用冒号隔开空行请求头后面的空行是必须的即使第四行请求数据为空行第三行也必须是空行请求数据也叫主体可以添加任意类型的数据 以下是通过抓包得到的http请求报文 GET http://jsuacm.cn/ HTTP/1.1 //Get为请求方法URL为请求资源1.1为http版本 Host: jsuacm.cn Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3877.400 QQBrowser/10.8.4506.400 Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/webp,image/apng,*/*;q0.8 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q0.9//”请求数据”(GET方式的请求一般不包含)常用的头部信息汇总 头部名称类型作用说明示例值Host请求头指定请求的目标主机名和端口号HTTP/1.1 必须包含Host: www.example.comUser-Agent请求头标识客户端浏览器、操作系统等信息Mozilla/5.0 (Windows NT 10.0)...Accept请求头指定客户端可接受的响应内容类型MIME 类型text/html,application/xhtmlxmlAccept-Language请求头指定客户端可接受的语言en-US,en;q0.9,zh-CN;q0.8Accept-Encoding请求头指定客户端可接受的编码方式如压缩格式gzip, deflateAuthorization请求头提供身份验证凭证如 Bearer Token、Basic AuthBearer tokenReferer请求头标明当前请求的来源页面 URLhttps://www.google.com/If-Match请求头条件请求头用于验证资源 ETag 是否匹配67ab43If-None-Match请求头条件请求头验证资源 ETag 是否不匹配用于缓存更新67ab43If-Modified-Since请求头条件请求头验证资源是否在指定时间后被修改Wed, 21 Oct 2023 07:28:00 GMTCookie请求头客户端随请求发送的 Cookie 数据sessionidabc123GET/ POST的区别 GET最常见的一种请求方式当客户端要从服务器中读取文档时当点击网页上的链接或者通过在浏览器的地址栏输入网址来浏览网页的使用的都是GET方式。GET方法要求服务器将URL定位的资源放在响应报文的数据部分回送给客户端。使用GET方法时请求参数和对应的值附加在URL后面利用一个问号“?”代表URL的结尾与请求参数的开始传递参数长度受限制。 GET方式的请求一般不包含”请求数据”部分请求数据以地址的形式表现在请求行。显然这种方式不适合传送私密数据。另外由于不同的浏览器对地址的字符限制也有所不同一般最多只能识别1024个字符所以如果需要传送大量数据的时候也不适合使用GET方式。 和get一样很常见对于上面提到的不适合使用GET方式的情况可以考虑使用POST方式因为使用POST方法可以允许客户端给服务器提供信息较多。POST方法将请求参数封装在HTTP请求数据中以名称/值的形式出现可以传输大量数据这样POST方式对传送的数据大小没有限制而且也不会显示在URL中 简单来讲就是GET一般用于我们点击网页其他链接时使用POST一般就是我们从网页上下载资源的时候使用 (2) 响应报文 由状态行消息报头空行响应正文四个部分组成 状态行由HTTP协议版本号状态码状态消息 三部分组成消息报头用来说明客户端要使用的一些附加信息空行响应正文主要就是服务端向客户端发送的数据比如一个页面、照片、视频等 以下是抓取的一段响应报文 HTTP/1.1 200 OK Server: nginx/1.18.0 (Ubuntu) Date: Wed, 20 Oct 2021 06:46:15 GMT Content-Type: text/html; charsetUTF-8 Connection: keep-alive Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Content-Length: 737265!DOCTYPE html html langen headmeta charsetutf-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1meta namedescription contentmeta nameauthor contentlink relicon href../../favicon.icotitle吉首大学 /titleHTTP状态码与请求方法 HTTP有5种类型的状态码具体的 1xx指示信息—表示请求已接收继续处理。 2xx成功—表示请求正常处理完毕。 200 OK客户端请求被正常处理。 206 Partial content客户端进行了范围请求。 3xx重定向—要完成请求必须进行更进一步的操作。 301 Moved Permanently永久重定向该资源已被永久移动到新位置将来对该资源访问都要使用本响应返回的若干个URI之一。 302 Found临时重定向请求的资源临时从不同的URI中获得。 4xx客户端错误—请求有语法错误服务器无法处理请求。 400 Bad Request请求报文存在语法错误。 403 Forbidden请求被服务器拒绝。 404 Not Found请求不存在服务器上找不到请求的资源。 5xx服务器端错误—服务器处理请求出错。 500 Internal Server Error服务器在执行请求时出现错误。 执行逻辑 首先主线程接收到一个客户端发来的事件如读/写等并将该事件按照事件类型标识并加入任务队列 eventLoop() ......//处理客户连接上接收到的数据else if (events[i].events EPOLLIN){dealwithread(sockfd);}else if (events[i].events EPOLLOUT){dealwithwrite(sockfd);......}void WebServer::dealwithread(int sockfd) {util_timer *timer users_timer[sockfd].timer;//reactor(反应堆),就是IO多路复用收到事件后根据事件类型分配给某个线程if (1 m_actormodel){if (timer){adjust_timer(timer);}//若监测到读事件将该事件放入请求队列m_pool-append(users sockfd, 0); //users是一个数组指针sockfd是索引因此这个表示的就是当前处理的客户端的对象//stat0表示read事件1表示write事件while (true){if (1 users[sockfd].improv){if (1 users[sockfd].timer_flag){deal_timer(timer, sockfd);users[sockfd].timer_flag 0;}users[sockfd].improv 0;break;}}}如果有事件添加进入任务队列则会通知线程池有空闲线程则会取出任务来进行执行执行线程执行函数run()内核是run函数但是run不是静态函数所以不能作为线程执行函数而是在外层套了一个壳的worker()函数 void threadpoolT::run() {while (true){m_queuestat.wait();//等待信号m_queuelocker.lock();if (m_workqueue.empty()){m_queuelocker.unlock();continue;}T *request m_workqueue.front();m_workqueue.pop_front();m_queuelocker.unlock();if (!request)continue;if (1 m_actor_model) //reactor{if (0 request-m_state){if (request-read_once()){request-improv 1;connectionRAII mysqlcon(request-mysql, m_connPool);request-process();}else{request-improv 1;request-timer_flag 1;}}else{if (request-write()){request-improv 1;}else{request-improv 1;request-timer_flag 1;}}}else{connectionRAII mysqlcon(request-mysql, m_connPool);request-process();}} }然后根据事件的类型(request-state)来选择执行相应的函数这里我们以读事件为例。首先客户端发来请求响应服务端需要先将客户端发来的请求响应的内容保存下来然后再进行解析保存请求响应的函数即是read_once()函数 该函数的逻辑也比较简单主要就是将套接字发送的内容储存到m_read_buf这个缓存区中 //循环读取客户数据直到无数据可读或对方关闭连接 //非阻塞ET工作模式下需要一次性将数据读完 bool http_conn::read_once() {if (m_read_idx READ_BUFFER_SIZE){return false;}int bytes_read 0;//LT读取数据if (0 m_TRIGMode){bytes_read recv(m_sockfd, m_read_buf m_read_idx, READ_BUFFER_SIZE - m_read_idx, 0);m_read_idx bytes_read;if (bytes_read 0){return false;}return true;}//ET读数据else{while (true){bytes_read recv(m_sockfd, m_read_buf m_read_idx, READ_BUFFER_SIZE - m_read_idx, 0);if (bytes_read -1){if (errno EAGAIN || errno EWOULDBLOCK)break;return false;}else if (bytes_read 0){return false;}m_read_idx bytes_read;}return true;} }我们得到缓冲区中的请求响应后就需要对其进行解析解析函数为process()函数这个函数会先使用process_read()函数对请求响应进行解析然后使用process_write()输出回应报文 void http_conn::process() {HTTP_CODE read_ret process_read(); // 请求报文处理限定结果在枚举范围之内if (read_ret NO_REQUEST) //如果请求不完整需要继续接收请求数据{modfd(m_epollfd, m_sockfd, EPOLLIN, m_TRIGMode);return;}bool write_ret process_write(read_ret);//相应报文处理if (!write_ret){close_conn();}modfd(m_epollfd, m_sockfd, EPOLLOUT, m_TRIGMode); }process_read()函数是请求报文解析函数是http的核心函数之一我们可以结合下面的图来看 /* 该函数为请求报文处理函数通过while循环来实现对主从状态机的封装其中主状态机为process_read()函数从状态机为parse_line()函数*/ http_conn::HTTP_CODE http_conn::process_read() {LINE_STATUS line_status LINE_OK;HTTP_CODE ret NO_REQUEST;char *text 0;//m_checked_state 主状态机状态为CHECK_STATE_REQUESTLINE时该条件涉及解析消息体//line_status 从状态机状态转移为LINE_OK时该条件涉及解析请求行while ((m_check_state CHECK_STATE_CONTENT line_status LINE_OK) || ((line_status parse_line()) LINE_OK)){text get_line(); //得到改行的具体内容m_start_line m_checked_idx;LOG_INFO(%s, text);switch (m_check_state){case CHECK_STATE_REQUESTLINE: //请求行初始化的时候定义了{ret parse_request_line(text);if (ret BAD_REQUEST)return BAD_REQUEST;break;}case CHECK_STATE_HEADER: //头信息{ret parse_headers(text);if (ret BAD_REQUEST)return BAD_REQUEST;else if (ret GET_REQUEST){return do_request();}break;}case CHECK_STATE_CONTENT: //消息体{ret parse_content(text);if (ret GET_REQUEST)return do_request();line_status LINE_OPEN;break;}default:return INTERNAL_ERROR;}}return NO_REQUEST; }6. 其中主状态机则为process_read()函数从状态机为parse_line()函数parse_line主要作用就是从读缓冲区中读取一行内容并将每一行结尾的\r\n改为\0\0。 //从状态机用于分析出一行内容 //返回值为行的读取状态有LINE_OK,LINE_BAD,LINE_OPEN http_conn::LINE_STATUS http_conn::parse_line() {char temp;for (; m_checked_idx m_read_idx; m_checked_idx){temp m_read_buf[m_checked_idx];if (temp \r){if ((m_checked_idx 1) m_read_idx)return LINE_OPEN;else if (m_read_buf[m_checked_idx 1] \n){m_read_buf[m_checked_idx] \0;m_read_buf[m_checked_idx] \0;return LINE_OK;}return LINE_BAD;}else if (temp \n){if (m_checked_idx 1 m_read_buf[m_checked_idx - 1] \r){m_read_buf[m_checked_idx - 1] \0;m_read_buf[m_checked_idx] \0;return LINE_OK;}return LINE_BAD;}}return LINE_OPEN; }如果返回LINE_OK表示改行已经读完并且该行的地址m_check_idx也已经更新接着通过get_line()这个函数就返回改行具体的内容了。 然后进入switch循环首先my_check_state的初始状态为CHECK_STATE_REQUESTLINE即解析请求行然后执行parse_request_line函数来解析函数如下 主要作用就是解析出m_method、m_url这两个属性然后将my_check_state的状态修改为CHECK_STATE_HEADER。 //解析http请求行获得请求方法目标url及http版本号 http_conn::HTTP_CODE http_conn::parse_request_line(char *text) {m_url strpbrk(text, \t);//用于查找第一个出现指定字符串的位置如果找到则返回指向该字符的指针否则返回NULLif (!m_url){return BAD_REQUEST;}*m_url \0;char *method text;if (strcasecmp(method, GET) 0)m_method GET;else if (strcasecmp(method, POST) 0){m_method POST;cgi 1; //是否启用POST}elsereturn BAD_REQUEST;m_url strspn(m_url, \t); //从m_url开始跳过空白字符返回第一个非空白字符的指针该作用是确保指针指向有效的字符m_version strpbrk(m_url, \t);if (!m_version)return BAD_REQUEST;*m_version \0;m_version strspn(m_version, \t);if (strcasecmp(m_version, HTTP/1.1) ! 0) //检查版本是否为1.1return BAD_REQUEST;if (strncasecmp(m_url, http://, 7) 0) //如果前缀包括http://则去掉{m_url 7;m_url strchr(m_url, /);}if (strncasecmp(m_url, https://, 8) 0) //同上{m_url 8;m_url strchr(m_url, /);}if (!m_url || m_url[0] ! /)return BAD_REQUEST;//当url为/时显示判断界面if (strlen(m_url) 1)strcat(m_url, judge.html);m_check_state CHECK_STATE_HEADER;return NO_REQUEST; }接下来是解析头部信息HEADER函数如下 其逻辑为如果检测到该行头部为“Connection:”、“keep-alive”等则赋予相应的属性值但是m_check_state不变 如果检测到“Content-length”这代表接下来是客户端发送过来的内容了这样的话就转变m_check_state的属性为CHECK_STATE_CONTENT代表下一次循环就要解析内容了 //解析http请求的一个头部信息 http_conn::HTTP_CODE http_conn::parse_headers(char *text) {if (text[0] \0){if (m_content_length ! 0){m_check_state CHECK_STATE_CONTENT;return NO_REQUEST;}return GET_REQUEST;}else if (strncasecmp(text, Connection:, 11) 0){text 11;text strspn(text, \t);if (strcasecmp(text, keep-alive) 0){m_linger true;}}else if (strncasecmp(text, Content-length:, 15) 0){text 15;text strspn(text, \t);m_content_length atol(text);}else if (strncasecmp(text, Host:, 5) 0){text 5;text strspn(text, \t);m_host text;}else{LOG_INFO(oop!unknow header: %s, text);}return NO_REQUEST; }以下是解析内容体的函数因为在该项目中客户端主要传输的对象很简单就只有输入的用户名和密码。 如果你希望在这个项目的基础上继续改进一个主要的改进方向就是这个你可以上传文件、图片等等。 那么既然客户端有上次内容那么服务器肯定需要对内容做一个回应或者处理那么就引出了接下来的do_request() 函数 //判断http请求是否被完整读入 http_conn::HTTP_CODE http_conn::parse_content(char *text) {if (m_read_idx (m_content_length m_checked_idx)){text[m_content_length] \0;//POST请求中最后为输入的用户名和密码m_string text;return GET_REQUEST;}return NO_REQUEST; }do_request() 函数因为比较长所以在这里就不直接粘贴出来了大家对照着源码来学习吧。 有请求报文就会有响应报文响应报文主要根据请求报文返回的状态来定义在process()函数中响应报文函数为process_write()函数 该函数的作用主要返回几种状态码如404、200等这些状态码的含义之前也已经叙述了大家可以翻到上面去看。 bool http_conn::process_write(HTTP_CODE ret) {switch (ret){case INTERNAL_ERROR:{add_status_line(500, error_500_title);add_headers(strlen(error_500_form));if (!add_content(error_500_form))return false;break;}case BAD_REQUEST:{add_status_line(404, error_404_title);add_headers(strlen(error_404_form));if (!add_content(error_404_form))return false;break;}case FORBIDDEN_REQUEST:{add_status_line(403, error_403_title);add_headers(strlen(error_403_form));if (!add_content(error_403_form))return false;break;}case FILE_REQUEST:{add_status_line(200, ok_200_title);if (m_file_stat.st_size ! 0){add_headers(m_file_stat.st_size);m_iv[0].iov_base m_write_buf;m_iv[0].iov_len m_write_idx;m_iv[1].iov_base m_file_address;m_iv[1].iov_len m_file_stat.st_size;m_iv_count 2;bytes_to_send m_write_idx m_file_stat.st_size;return true;}else{const char *ok_string htmlbody/body/html;add_headers(strlen(ok_string));if (!add_content(ok_string))return false;}}default:return false;}m_iv[0].iov_base m_write_buf;m_iv[0].iov_len m_write_idx;m_iv_count 1;bytes_to_send m_write_idx;return true; }这些基本上就是http的整个运行的逻辑框架了大家有什么不懂的评论区见~
http://www.pierceye.com/news/899339/

相关文章:

  • ae成品免费下载网站申请一个app多少钱
  • 我想自己在网站上发文章 怎样做免费观看高清正能量直播下载
  • 做网站万网长春建站模板展示
  • 广州专业建网站公司福州网站制作
  • 西安烽盈网站建设郑州营销网站托管
  • 诸几建设银行网站怎么维护好网站
  • 深圳市国外网站建设简单html5网页设计
  • 网站制作公司西南城乡建设部网站首页
  • 网站名和域名能一样吗企业网站建设硬件
  • 德州做网站公司怎么开网店淘宝
  • 苏州做网站优化的电商定制开发
  • 广西庆海建设发展有限公司网站昆山有做网站的公司吗
  • 前端课程网站wordpress 微博登陆
  • asp怎么做网站适配开发公司安置房项目工程推进大会
  • 学做网站可以赚钱吗怎么批量修改wordpress文章内容
  • 写作网站vir上海博大园林建设发展有限公司网站
  • wordpress video gallery网站代码优化怎么做
  • 厦门网站设计品牌企业互联网门户网站建设
  • 做名片模板网站中文响应式网站
  • 用tornado做网站石家庄 外贸网站建设公司
  • 档案网站建设网页wordpress keyshot
  • 鞍山制作网站哪家好建设银行员工网站
  • 手机怎么提升网站流量品牌型网站成功案例图片
  • 网站视频主持人制作网站开发 质量管理
  • 网站的外链建设计划石家庄市城乡建设部网站
  • 电子商务网站规划与建设论文电子商务营销方法
  • 宁波做网站费用电子商城开发网站开发
  • 太原市住房和城乡建设部网站免费的logo在线设计
  • 做it的在哪个网站找工作wordpress 幻燈片 插件
  • 湘潭做网站 i磐石网络博学网站建设公司