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

眉县网站建设企业网站建设的服务类型有哪些

眉县网站建设,企业网站建设的服务类型有哪些,关键词排名优化公司,怎么搭建本地网站1.结合代码分析请求报文响应 下面我们将介绍服务器如何响应请求报文#xff0c;并将该报文发送给浏览器端。首先介绍一些基础API#xff0c;然后结合流程图和代码对服务器响应请求报文进行详解。 基础API部分#xff0c;介绍stat、mmap、iovec、writev。 流程图部分…1.结合代码分析请求报文响应 下面我们将介绍服务器如何响应请求报文并将该报文发送给浏览器端。首先介绍一些基础API然后结合流程图和代码对服务器响应请求报文进行详解。 基础API部分介绍stat、mmap、iovec、writev。 流程图部分描述服务器端响应请求报文的逻辑各模块间的关系。 代码部分结合代码对服务器响应请求报文进行详解。 1.1 基础API 为了更好的源码阅读体验这里提前对代码中使用的一些API进行简要介绍更丰富的用法可以自行查阅资料。 stat stat函数用于取得指定文件的文件属性并将文件属性存储在结构体stat里这里仅对其中用到的成员进行介绍。 #include sys/types.h #include sys/stat.h #include unistd.h//获取文件属性存储在statbuf中 int stat(const char *pathname, struct stat *statbuf);struct stat {mode_t st_mode; /* 文件类型和权限 */off_t st_size; /* 文件大小字节数*/ };mmap 用于将一个文件或其他对象映射到内存提高文件的访问速度。 void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset); int munmap(void* start,size_t length);start映射区的开始地址设置为0时表示由系统决定映射区的起始地址length映射区的长度prot期望的内存保护标志不能与文件的打开模式冲突 PROT_READ 表示页内容可以被读取flags指定映射对象的类型映射选项和映射页是否可以共享 MAP_PRIVATE 建立一个写入时拷贝的私有映射内存区域的写入不会影响到原文件fd有效的文件描述符一般是由open()函数返回 off_toffset被映射对象内容的起点 iovec 定义了一个向量元素通常这个结构用作一个多元素的数组。 struct iovec {void *iov_base; /* starting address of buffer */size_t iov_len; /* size of buffer */ };iov_base指向数据的地址iov_len表示数据的长度 writev writev函数用于在一次函数调用中写多个非连续缓冲区有时也将这该函数称为聚集写。 #include sys/uio.h ssize_t writev(int filedes, const struct iovec *iov, int iovcnt);filedes表示文件描述符iov为前述io向量机制结构体ioveciovcnt为结构体的个数 若成功则返回已写的字节数若出错则返回-1。 writev以顺序iov[0]iov[1]至iov[iovcnt-1]从缓冲区中聚集输出数据。 writev返回输出的字节总数通常它应等于所有缓冲区长度之和。 特别注意 循环调用writev时需要重新处理iovec中的指针和长度该函数不会对这两个成员做任何处理。writev的返回值为已写的字节数但这个返回值“实用性”并不高因为参数传入的是iovec数组计量单位是iovcnt而不是字节数我们仍然需要通过遍历iovec来计算新的基址另外写入数据的“结束点”可能位于一个iovec的中间某个位置因此需要调整临界iovec的io_base和io_len。 1.2 流程图 浏览器端发出HTTP请求报文服务器端接收该报文并调用process_read对其进行解析根据解析结果HTTP_CODE进入相应的逻辑和模块。 其中服务器子线程完成报文的解析与响应主线程监测读写事件调用read_once和http_conn::write完成数据的读取与发送。 HTTP_CODE含义 表示HTTP请求的处理结果在头文件中初始化了八种情形在报文解析与响应中只用到了七种。 NO_REQUEST 请求不完整需要继续读取请求报文数据跳转主线程继续监测读事件GET_REQUEST 获得了完整的HTTP请求调用do_request完成请求资源映射NO_RESOURCE 请求资源不存在跳转process_write完成响应报文BAD_REQUEST HTTP请求报文有语法错误或请求资源为目录跳转process_write完成响应报文FORBIDDEN_REQUEST 请求资源禁止访问没有读取权限跳转process_write完成响应报文FILE_REQUEST 请求资源可以正常访问跳转process_write完成响应报文INTERNAL_ERROR 服务器内部错误该结果在主状态机逻辑switch的default下一般不会触发 1.3 代码分析 do_request process_read函数的返回值是对请求的文件分析后的结果一部分是语法错误导致的BAD_REQUEST一部分是do_request的返回结果.该函数将网站根目录和url文件拼接然后通过stat判断该文件属性。另外为了提高访问速度通过mmap进行映射将普通文件映射到内存逻辑地址。 为了更好的理解请求资源的访问流程这里对各种各页面跳转机制进行简要介绍。其中浏览器网址栏中的字符即url可以将其抽象成ip:port/xxxxxx通过html文件的action属性进行设置。 m_url为请求报文中解析出的请求资源以/开头也就是xxx项目中解析后的m_url有8种情况。 / GET请求跳转到judge.html即欢迎访问页面/0 POST请求跳转到register.html即注册页面/1 POST请求跳转到log.html即登录页面/2CGISQL.cgi POST请求进行登录校验验证成功跳转到welcome.html即资源请求成功页面验证失败跳转到logError.html即登录失败页面/3CGISQL.cgi POST请求进行注册校验注册成功跳转到log.html即登录页面注册失败跳转到registerError.html即注册失败页面/5 POST请求跳转到picture.html即图片请求页面/6 POST请求跳转到video.html即视频请求页面/7 POST请求跳转到fans.html即关注页面 如果大家对上述设置方式不理解不用担心。具体的登录和注册校验功能会在第1下面进行详解到时候还会针对html进行介绍。 //网站根目录文件夹内存放请求的资源和跳转的html文件 const char* doc_root/home/wfc/obj/MyWebserver/root;http_conn::HTTP_CODE http_conn::do_request() {//将初始化的m_real_file赋值为网站根目录strcpy(m_real_file,doc_root);int lenstrlen(doc_root);//找到m_url中/的位置const char *p strrchr(m_url, /); //实现登录和注册校验if(cgi1 (*(p1) 2 || *(p1) 3)){//根据标志判断是登录检测还是注册检测//同步线程登录校验//CGI多进程登录校验}//如果请求资源为/0表示跳转注册界面if(*(p1) 0){char *m_url_real (char *)malloc(sizeof(char) * 200);strcpy(m_url_real,/register.html);//将网站目录和/register.html进行拼接更新到m_real_file中strncpy(m_real_filelen,m_url_real,strlen(m_url_real));free(m_url_real);}//如果请求资源为/1表示跳转登录界面else if( *(p1) 1){char *m_url_real (char *)malloc(sizeof(char) * 200);strcpy(m_url_real,/log.html);//将网站目录和/log.html进行拼接更新到m_real_file中strncpy(m_real_filelen,m_url_real,strlen(m_url_real));free(m_url_real);}else//如果以上均不符合即不是登录和注册直接将url与网站目录拼接//这里的情况是welcome界面请求服务器上的一个图片strncpy(m_real_filelen,m_url,FILENAME_LEN-len-1);//通过stat获取请求资源文件信息成功则将信息更新到m_file_stat结构体//失败返回NO_RESOURCE状态表示资源不存在if(stat(m_real_file,m_file_stat)0)return NO_RESOURCE;//判断文件的权限是否可读不可读则返回FORBIDDEN_REQUEST状态if(!(m_file_stat.st_modeS_IROTH))return FORBIDDEN_REQUEST;//判断文件类型如果是目录则返回BAD_REQUEST表示请求报文有误if(S_ISDIR(m_file_stat.st_mode))return BAD_REQUEST;//以只读方式获取文件描述符通过mmap将该文件映射到内存中int fdopen(m_real_file,O_RDONLY);m_file_address(char*)mmap(0,m_file_stat.st_size,PROT_READ,MAP_PRIVATE,fd,0);//避免文件描述符的浪费和占用close(fd);//表示请求文件存在且可以访问return FILE_REQUEST; }process_write 根据do_request的返回状态服务器子线程调用process_write向m_write_buf中写入响应报文。 add_status_line函数添加状态行http/1.1 状态码 状态消息 add_headers函数添加消息报头内部调用add_content_length和add_linger函数content-length记录响应报文长度用于浏览器端判断服务器是否发送完数据connection记录连接状态用于告诉浏览器端保持长连接add_blank_line添加空行 上述涉及的5个函数均是内部调用add_response函数更新m_write_idx指针和缓冲区m_write_buf中的内容。 bool http_conn::add_response(const char* format,...) {//如果写入内容超出m_write_buf大小则报错if(m_write_idxWRITE_BUFFER_SIZE)return false;//定义可变参数列表va_list arg_list;//将变量arg_list初始化为传入参数va_start(arg_list,format);//将数据format从可变参数列表写入缓冲区写返回写入数据的长度int lenvsnprintf(m_write_bufm_write_idx,WRITE_BUFFER_SIZE-1-m_write_idx,format,arg_list);//如果写入的数据长度超过缓冲区剩余空间则报错if(len(WRITE_BUFFER_SIZE-1-m_write_idx)){va_end(arg_list);return false;}//更新m_write_idx位置m_write_idxlen;//清空可变参列表va_end(arg_list);return true; }//添加状态行 bool http_conn::add_status_line(int status,const char* title) {return add_response(%s %d %s\r\n,HTTP/1.1,status,title); } //添加消息报头具体的添加文本长度、连接状态和空行 bool http_conn::add_headers(int content_len) {add_content_length(content_len);add_linger();add_blank_line(); }//添加Content-Length表示响应报文的长度 bool http_conn::add_content_length(int content_len) {return add_response(Content-Length:%d\r\n,content_len); }//添加文本类型这里是html bool http_conn::add_content_type() {return add_response(Content-Type:%s\r\n,text/html); }//添加连接状态通知浏览器端是保持连接还是关闭 bool http_conn::add_linger() {return add_response(Connection:%s\r\n,(m_lingertrue)?keep-alive:close); } //添加空行 bool http_conn::add_blank_line() {return add_response(%s,\r\n); }//添加文本content bool http_conn::add_content(const char* content) {return add_response(%s,content); } 响应报文分为两种一种是请求文件的存在通过io向量机制iovec声明两个iovec第一个指向m_write_buf第二个指向mmap的地址m_file_address一种是请求出错这时候只申请一个iovec指向m_write_buf。 iovec是一个结构体里面有两个元素指针成员iov_base指向一个缓冲区这个缓冲区是存放的是writev将要发送的数据。成员iov_len表示实际写入的长度 bool http_conn::process_write(HTTP_CODE ret) {switch(ret){//内部错误500case INTERNAL_ERROR:{//状态行add_status_line(500,error_500_title);//消息报头add_headers(strlen(error_500_form));if(!add_content(error_500_form))return false;break;}//报文语法有误404case BAD_REQUEST:{add_status_line(404,error_404_title);add_headers(strlen(error_404_form));if(!add_content(error_404_form))return false;break;}//资源没有访问权限403case FORBIDDEN_REQUEST:{add_status_line(403,error_403_title);add_headers(strlen(error_403_form));if(!add_content(error_403_form))return false;break;}//文件存在200case FILE_REQUEST:{add_status_line(200,ok_200_title);//如果请求的资源存在if(m_file_stat.st_size!0){add_headers(m_file_stat.st_size);//第一个iovec指针指向响应报文缓冲区长度指向m_write_idxm_iv[0].iov_basem_write_buf;m_iv[0].iov_lenm_write_idx;//第二个iovec指针指向mmap返回的文件指针长度指向文件大小m_iv[1].iov_basem_file_address;m_iv[1].iov_lenm_file_stat.st_size;m_iv_count2;//发送的全部数据为响应报文头部信息和文件大小bytes_to_send m_write_idx m_file_stat.st_size;return true;}else{//如果请求的资源大小为0则返回空白html文件const char* ok_stringhtmlbody/body/html;add_headers(strlen(ok_string));if(!add_content(ok_string))return false;}}default:return false;}//除FILE_REQUEST状态外其余状态只申请一个iovec指向响应报文缓冲区m_iv[0].iov_basem_write_buf;m_iv[0].iov_lenm_write_idx;m_iv_count1;return true; }http_conn::write 服务器子线程调用process_write完成响应报文随后注册epollout事件。服务器主线程检测写事件并调用http_conn::write函数将响应报文发送给浏览器端。 该函数具体逻辑如下 在生成响应报文时初始化byte_to_send包括头部信息和文件数据大小。通过writev函数循环发送响应报文数据根据返回值更新byte_have_send和iovec结构体的指针和长度并判断响应报文整体是否发送成功。 若writev单次发送成功更新byte_to_send和byte_have_send的大小若响应报文整体发送成功,则取消mmap映射,并判断是否是长连接. 长连接重置http类实例注册读事件不关闭连接短连接直接关闭连接若writev单次发送不成功判断是否是写缓冲区满了。 若不是因为缓冲区满了而失败取消mmap映射关闭连接若eagain则满了更新iovec结构体的指针和长度并注册写事件等待下一次写事件触发当写缓冲区从不可写变为可写触发epollout因此在此期间无法立即接收到同一用户的下一请求但可以保证连接的完整性。 bool http_conn::write() {int temp 0;int newadd 0;//若要发送的数据长度为0//表示响应报文为空一般不会出现这种情况if(bytes_to_send0){modfd(m_epollfd,m_sockfd,EPOLLIN);init();return true;}while (1){ //将响应报文的状态行、消息头、空行和响应正文发送给浏览器端tempwritev(m_sockfd,m_iv,m_iv_count);//正常发送temp为发送的字节数if (temp 0){//更新已发送字节bytes_have_send temp;//偏移文件iovec的指针newadd bytes_have_send - m_write_idx;}if (temp -1){//判断缓冲区是否满了if (errno EAGAIN){//第一个iovec头部信息的数据已发送完发送第二个iovec数据if (bytes_have_send m_iv[0].iov_len){//不再继续发送头部信息m_iv[0].iov_len 0;m_iv[1].iov_base m_file_address newadd;m_iv[1].iov_len bytes_to_send;}//继续发送第一个iovec头部信息的数据else{m_iv[0].iov_base m_write_buf bytes_to_send;m_iv[0].iov_len m_iv[0].iov_len - bytes_have_send;}//重新注册写事件modfd(m_epollfd, m_sockfd, EPOLLOUT);return true;}//如果发送失败但不是缓冲区问题取消映射unmap();return false;}//更新已发送字节数bytes_to_send - temp;//判断条件数据已全部发送完if (bytes_to_send 0){unmap();//在epoll树上重置EPOLLONESHOT事件modfd(m_epollfd,m_sockfd,EPOLLIN);//浏览器的请求为长连接if(m_linger){//重新初始化HTTP对象init();return true;}else{return false;}}} }书中原代码的write函数不严谨这里对其中的Bug进行了修复可以正常传输大文件。
http://www.yutouwan.com/news/434215/

相关文章:

  • 互联网建站公司有哪些网页型网站
  • 佛山商城网站建设新商盟网站开发时间
  • 网站聊天系统怎么做教育网站建设 思维导图
  • 网站制作的公司哪家比较好云主机怎么上传网站
  • 沧州市科一网站沈阳网站设计开发
  • 设计师网站接单百度添加到桌面
  • 微信公众号制作网站郑州艾特网站建设公司
  • 立邦漆官方网站官网手机开发框架
  • 怎么在网站里给图片做超链接淘宝店铺推广
  • 网站设计专业建站公司怀化招标网站
  • 石家庄大的网站开发公司辽宁省建设工程信息网网
  • 在阿里云里网站建设的步骤过程微信小程序开发技术
  • 互联在线app开发网站怎么添加网站
  • 网站小图标素材下载天津百度首页优化排名
  • 有哪些网站可以做家教wordpress 有市场吗
  • 电商型网站是否是趋势甘肃建投土木工程建设有限公司网站
  • 怎么查网站备案asp.net企业网站管理系统
  • 怎样给自己做网站惠安县住房和城乡建设部网站
  • 怎样搭建网站视频教程接单网个人接单
  • 网站建设的文章做盗版网站违法吗
  • 重庆网站首页制作鄂州网站建设哪家好
  • 网站线框图用什么做写一篇软文1000字
  • 集团网站设计专业团队网站建设主要内容
  • c 鲜花店网站建设做旅游计划的网站
  • 生鲜做的好的网站手机优化设置
  • 网站开发代码无中文好f123网站
  • html网站开发wordpress内置编辑器
  • 设计师找工作的网站三星网上商城退款很慢
  • 上海定制网站建设费用河东苏州网站建设
  • 郑州网站建设公司制作定制免费友情链接交换平台