位置: IT常识 - 正文

实现自己的http server loop_in_codes C++博客

编辑:rootadmin
实现自己的http server - loop_in_codes - C++博客实现自己的http serverWrite your own http server author : Kevin Ly 实现自己的http server

推荐整理分享实现自己的http server loop_in_codes C++博客,希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:,内容如对您有帮助,希望把文章链接给更多的朋友!

Write your own http server

author : Kevin Lynx

Why write your own?

看这个问题的人证明你知道什么是http server,世界上有很多各种规模的http server,为什么要自己实现一个?其实没什么理由。我自己问自己,感觉就是在自己娱乐自己,或者说只是练习下网络编程,或者是因为某日我看到某个库宣称自己附带一个小型的http server时,我不知道是什么东西,于是就想自己去实现一个。

What's httpd ?

httpd就是http daemon,这个是类unix系统上的名称,也就是http server。httpd遵循HTTP协议,响应HTTP客户端的request,然后返回response。 那么,什么是HTTP协议?最简单的例子,就是你的浏览器与网页服务器之间使用的应用层协议。虽然官方文档说HTTP协议可以建立在任何可靠传输的协议之上,但是就我们所见到的,HTTP还是建立在TCP之上的。 httpd最简单的response是返回静态的HTML页面。在这里我们的目标也只是一个响应静态网页的httpd而已(也许你愿意加入CGI特性)。

More details about HTTP protocol

在这里有必要讲解HTTP协议的更多细节,因为我们的httpd就是要去解析这个协议。 关于HTTP协议的详细文档,可以参看rfc2616。但事实上对于实现一个简单的响应静态网页的httpd来说,完全没必要读这么一分冗长的文档。在这里我推荐<HTTP Made Really Easy>,以下内容基本取自于本文档。

- HTTP协议结构 HTTP协议无论是请求报文(request message)还是回应报文(response message)都分为四部分: * 报文头 (initial line ) * 0个或多个header line * 空行(作为header lines的结束) * 可选body HTTP协议是基于行的协议,每一行以\r\n作为分隔符。报文头通常表明报文的类型(例如请求类型),报文头只占一行;header line 附带一些特殊信息,每一个header line占一行,其格式为name:value,即以分号作为分隔;空行也就是一个\r\n;可选body通常 包含数据,例如服务器返回的某个静态HTML文件的内容。举个例子,以下是一个很常见的请求报文,你可以截获浏览器发送的数据 包而获得:

1 GET /index.html HTTP/1.1 2 Accept-Language: zh-cn 3 Accept-Encoding: gzip, deflate 4 User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; MAXTHON 2.0) 5 Host: localhost 6 Connection: Keep-Alive 7 我为每一行都添加了行号,第1行就是initial line,2-6行是header lines,7行是一个header line的结束符,没有显示出来。 以下是一个回应报文: 1 HTTP/1.1 200 OK 2 Server: klhttpd/0.1.0 3 Content-Type: text/html 4 Content-Length: 67 5 6 <head><head><title>index.html</title></head><body>index.html</body> 第6行就是可选的body,这里是index.html这个文件的内容。

- HTTP request method 因为我们做的事服务器端,所以我们重点对请求报文做说明。首先看initial line,该行包含几个字段,每个字段用空格分开,例 如以上的GET /index.html HTTP/1.1就可以分为三部分:GET、/index.html、HTTP/1.1。其中第一个字段GET就是所谓的request method。它表明请求类型,HTTP有很多method,例如:GET、POST、HEAD等。

就我们的目标而言,我们只需要实现对GET和HEAD做响应即可。

GET是最普遍的method,表示请求一个资源。什么是资源?诸如HTML网页、图片、声音文件等都是资源。顺便提一句,HTTP协议 中为每一个资源设置一个唯一的标识符,就是所谓的URI(更宽泛的URL)。 HEAD与GET一样,不过它不请求资源内容,而是请求资源信息,例如文件长度等信息。

实现自己的http server  loop_in_codes  C++博客

- More detail 继续说说initial line后面的内容: 对应于GET和HEAD两个method,紧接着的字段就是资源名,其实从这里可以看出,也就是文件名(相对于你服务器的资源目录),例 如这里的/index.html;最后一个字段表明HTTP协议版本号。目前我们只需要支持HTTP1.1和1.0,没有多大的技术差别。

然后是header line。我们并不需要关注每一个header line。我只罗列有用的header line : - Host : 对于HTTP1.1而言,请求报文中必须包含此header,如果没有包含,服务器需要返回bad request错误信息。 - Date : 用于回应报文,用于客户端缓存数据用。 - Content-Type : 用于回应报文,表示回应资源的文件类型,以MIME形式给出。什么是MIME?它们都有自己的格式,例如: text/html, image/jpg, image/gif等。 - Content-Length : 用于回应报文,表示回应资源的文件长度。

body域很简单,你只需要将一个文件全部读入内存,然后附加到回应报文段后发送即可,即使是二进制数据。

- 回应报文 之前提到的一个回应报文例子很典型,我们以其为例讲解。首先是initial line,第一个字段表明HTTP协议版本,可以直接以请求 报文为准(即请求报文版本是多少这里就是多少);第二个字段是一个status code,也就是回应状态,相当于请求结果,请求结果 被HTTP官方事先定义,例如200表示成功、404表示资源不存在等;最后一个字段为status code的可读字符串,你随便给吧。

回应报文中最好跟上Content-Type、Content-Length等header。

具体实现 正式写代码之前我希望你能明白HTTP协议的这种请求/回应模式,即客户端发出一个请求,然后服务器端回应该请求。然后继续这个过程(HTTP1.1是长连接模式,而HTTP1.0是短连接,当服务器端返回第一个请求时,连接就断开了)。 这里,我们无论客户端,例如浏览器,发出什么样的请求,请求什么资源,我们都回应相同的数据:

/**//*阻塞地接受一个客户端连接*/SOCKETcon=accept(s,0,0);/**//*recvrequest*/charrequest[1024]={0};ret=recv(con,request,sizeof(request),0);printf(request);/**//*whateverwerecv,wesend200response*/{charcontent[]="<head><head><title>index.html</title></head><body>index.html</body>";charresponse[512];sprintf(response,"HTTP/1.1200OK\r\nContent-Type:text/html\r\nContent-Length:%d\r\n\r\n%s",strlen(content),content);ret=send(con,response,strlen(response),0);}closesocket(con);

程序以最简单的阻塞模式运行,我们可以将重点放在协议的分析上。运行程序,在浏览器里输入http://localhost:8080/index.html,然后就可以看到浏览器正常显示content中描述的HTML文件。假设程序在8080端口监听。

现在你基本上明白了整个工作过程,我们可以把代码写得更全面一点,例如根据GET的URI来载入对应的文件然后回应给客户端。其实这个很简单,只需要从initial line里解析出(很一般的字符串解析)URI字段,然后载入对应的文件即可。例如以下函数:

voidhttp_response(SOCKETcon,constchar*request){/**//*getthemethod*/char*token=strtok(request,"");char*uri=strtok(0,"");charfile[64];sprintf(file,".%s",uri);{/**//*loadthefilecontent*/FILE*fp=fopen(file,"rb");if(fp==0){/**//*response404statuscode*/charresponse[]="HTTP/1.1404NOTFOUND\r\n\r\n";send(con,response,strlen(response),0);}else{/**//*responsetheresource*//**//*first,loadthefile*/intfile_size;char*content;charresponse[1024];fseek(fp,0,SEEK_END);file_size=ftell(fp);fseek(fp,0,SEEK_SET);content=(char*)malloc(file_size+1);fread(content,file_size,1,fp);content[file_size]=0;sprintf(response,"HTTP/1.1200OK\r\nContent-Type:text/html\r\nContent-Length:%d\r\n\r\n%s",file_size,content);send(con,response,strlen(response),0);free(content);}}}

其他 要将这个简易的httpd做完善,我们还需要注意很多细节。包括:对不支持的method返回501错误;对于HTTP1.1要求有Host这个header;为了支持客户端cache,需要添加Date header;支持HEAD请求等。

相关下载中我提供了一个完整的httpd library,纯C的代码,在其上加上一层资源载入即可实现一个简单的httpd。在这里我将对代码做简要的说明: evbuffer.h/buffer.c : 取自libevent的buffer,用于缓存数据; klhttp-internal.h/klhttp-internal.c :主要用于处理/解析HTTP请求,以及创建回应报文; klhttp-netbase.h/klhttp-netbase.c :对socket api的一个简要封装,使用select模型; klhttp.h/klhttp.c :库的最上层,应用层主要与该层交互,这一层主要集合internal和netbase。 test_klhttp.c :一个测试例子。

相关下载: klhttpd 文中相关代码

参考资料:

http://www.w3.org/Protocols/rfc2616/rfc2616.htmlhttp://jmarshall.com/easy/http/http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

本文链接地址:https://www.jiuchutong.com/zhishi/304100.html 转载请保留说明!

上一篇:【HDLBits刷题笔记】13 Finite State Machines(刷题笔贴吧)

下一篇:HTTP Tunneling (HTTP Proxy Socket Client)

  • 荣耀X30Max是什么系统(荣耀x30max是什么意思)

    荣耀X30Max是什么系统(荣耀x30max是什么意思)

  • 2021网易云唱歌的草稿箱在哪(网易云唱这首歌)

    2021网易云唱歌的草稿箱在哪(网易云唱这首歌)

  • 红米k30pro刷新率是多少(红米k30Pro刷新率)

    红米k30pro刷新率是多少(红米k30Pro刷新率)

  • 华为手机暗夜模式怎么设置(华为手机暗夜模式)

    华为手机暗夜模式怎么设置(华为手机暗夜模式)

  • 台式电脑浏览器打不开网页是什么原因(台式电脑浏览器打不开怎么办)

    台式电脑浏览器打不开网页是什么原因(台式电脑浏览器打不开怎么办)

  • 淘宝交易成功后还可以申请退货退款吗(淘宝交易成功后钱到哪里去了)

    淘宝交易成功后还可以申请退货退款吗(淘宝交易成功后钱到哪里去了)

  • qq邮箱最多发多少个g(qq邮箱最多发多少照片)

    qq邮箱最多发多少个g(qq邮箱最多发多少照片)

  • 美团骑手可以自己安排时间吗(美团骑手可以自己注册接单吗)

    美团骑手可以自己安排时间吗(美团骑手可以自己注册接单吗)

  • 苹果x背面有一串英文(苹果x背面有一条黑线)

    苹果x背面有一串英文(苹果x背面有一条黑线)

  • 预售商品无法加入购物车(预售商品无法加购怎么办)

    预售商品无法加入购物车(预售商品无法加购怎么办)

  • 订单待配货什么意思(订单待配货一般多少天)

    订单待配货什么意思(订单待配货一般多少天)

  • honor 9x如何隐藏应用(华为荣耀9如何隐藏)

    honor 9x如何隐藏应用(华为荣耀9如何隐藏)

  • a1567是第几代(a1567是苹果几代)

    a1567是第几代(a1567是苹果几代)

  • 微信文件不能超过100m怎么办(微信文件不能超过100m)

    微信文件不能超过100m怎么办(微信文件不能超过100m)

  • 手机演示模式怎么开(手机演示模式怎么解除)

    手机演示模式怎么开(手机演示模式怎么解除)

  • 微信群里可以发多长的视频(微信群里可以发多少钱的红包)

    微信群里可以发多长的视频(微信群里可以发多少钱的红包)

  • m6能插内存卡跟电话卡吗(m6插卡版的能插内存卡吗)

    m6能插内存卡跟电话卡吗(m6插卡版的能插内存卡吗)

  • 苹果手机下载不了软件怎么回事(苹果手机下载不了微信)

    苹果手机下载不了软件怎么回事(苹果手机下载不了微信)

  • 华为p30广角怎么调(华为p30广角怎么关闭)

    华为p30广角怎么调(华为p30广角怎么关闭)

  • 抖音粉丝列表怎么隐藏(抖音粉丝列表怎么排顺序)

    抖音粉丝列表怎么隐藏(抖音粉丝列表怎么排顺序)

  • 苹果6怎么进入nfc功能(苹果6怎么进入dfu模式刷机)

    苹果6怎么进入nfc功能(苹果6怎么进入dfu模式刷机)

  • qq文件传输助手在哪里(QQ文件传输助手图片)

    qq文件传输助手在哪里(QQ文件传输助手图片)

  • 微信语音怎么开启扩音(微信语音怎么开变声器?)

    微信语音怎么开启扩音(微信语音怎么开变声器?)

  • 淘宝卖家如何设置淘金币抵钱(淘宝卖家如何设置优惠券)

    淘宝卖家如何设置淘金币抵钱(淘宝卖家如何设置优惠券)

  • 手机接不到电话也打不出去怎么回事(手机接不到电话怎么回事)

    手机接不到电话也打不出去怎么回事(手机接不到电话怎么回事)

  • 抖音视频加载不出来(抖音视频加载不了是什么原因)

    抖音视频加载不出来(抖音视频加载不了是什么原因)

  • Bojo河,菲律宾宿务 (© Amazing Aerial Agency/Offset by Shutterstock)(菲律宾薄荷岛疫情最新消息)

    Bojo河,菲律宾宿务 (© Amazing Aerial Agency/Offset by Shutterstock)(菲律宾薄荷岛疫情最新消息)

  • 组成计税价格公式消费税
  • 其他业务收入在借方表示什么
  • 短期投资会计科目编码
  • 计提坏账准备需要纳税调增吗
  • 核定征收生产经营所得税率
  • 无形资产发生减值的原因
  • 法人转钱进公账要交税吗
  • 停产期间产生的费用怎么处理?
  • 化妆品进口环节消费税
  • 国外劳务费用是怎样产生的
  • 未开票收入为负数如何写说明
  • 广告业增值税税率6%是多少
  • 文化建设费的征收标准
  • 税控盘超期还能清卡吗
  • 递延所得税收益计算公式
  • 制造费用和劳务成本
  • 企业发给员工的福利要交税吗
  • 开发票征收品目怎么填
  • 城建税有哪些征税项目
  • 企业合并的会计分录
  • 业绩补偿协议
  • 小规模计提缴纳增值税
  • linux的使用场合
  • 进口关税和进口增值税怎么算
  • 跨年度增值税发票作废怎么退税
  • 小规模纳税人安装费税率
  • 安置房项目需要环评吗
  • 使用php进行mysql数据库编程的基本步骤
  • 公寓收费标准
  • 笔记本win10玩红警怎么全屏
  • bass boost system
  • 出售债券税费处理方法
  • yolov5解析
  • 使用二氧化碳灭火器时人应该站在什么位置
  • 今天端午节是几月几号啊
  • 个人房屋出租税票怎么开
  • 小企业会计准则和一般企业会计准则的区别
  • 一二级公路增值税税率
  • 发生的计提费用没有发生怎么办
  • openfoam中文教程
  • php无限分类实现不实用递归
  • sudo权限是什么意思
  • 机关事业单位以外包服务方式长期用工
  • 帝国cms phpcms
  • 申报错误要罚款吗
  • 对公付款对方不发货不退钱怎么处理
  • 表单数据提交时会触发什么事件
  • 季度所得税申报表本年累计怎么填
  • 政府补助的界定
  • 内部审计主要目的
  • 应收账款收不回来了应怎么做会计分录
  • 发票清单用什么章
  • 差旅费用包含哪些
  • 发票遗失重开需要收费吗?
  • 留存收益与未分配利润的关系
  • 总账建账的原则包括
  • 暂估入账后续处理
  • fedora安装xorg
  • aesm_service.exe是什么
  • windows隐藏功能
  • centos7如何添加永久静态路由
  • centos7怎么安装图形化界面
  • centos7.6忘记密码了怎么办
  • win7一直处于开机界面
  • win7怎样设置屏幕保护密码
  • ExtJS4中的requires使用方法示例介绍
  • Linux查看所有用户和密码
  • win10 putty
  • 零基础玩转python
  • 使用Math.floor与Math.random取随机整数的方法详解
  • python如何处理文本
  • javascript中math.ceil
  • SharedPreferences中的MODE_APPEND 和 MODE_PRIVATE 区别
  • 一个绿色的球英语怎么读
  • JavaScript Try...Catch 声明的 使用方法
  • python如何搭建环境
  • jquery自带的弹出框
  • 浅谈python 四种数值类型(int,long,float,complex)
  • 如何抵扣税款
  • 环保职责及管理范围
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设