加入收藏 | 设为首页 | 会员中心 | 我要投稿 好传媒网 (https://www.haochuanmei.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长资讯 > 外闻 > 正文

从零实现一个Http服务器

发布时间:2019-04-18 06:44:41 所属栏目:外闻 来源:高性能服务器开发
导读:我始终觉得,天生的出身很重要,但后天的努力更加重要,所以如今的很多科班往往不如后天努力的非科班。所以,我们需要重新给专业和专家下一个定义:所谓专业,就是别人不搞你搞,这就是你的专业;你和别人同时搞,你比别人搞的好,就是专家。 说到http协议

那么POST的数据放在什么位置呢?我们再12306网站https://kyfw.12306.cn/otn/login/init中登陆输入用户名和密码:

从零实现一个Http服务器

然后发现浏览器以POST方式组装了http协议包发送了我们的用户名、密码和其他一些信息,组装的包格式如下:

  1. POST /passport/web/login HTTP/1.1rn 
  2.  2Host: kyfw.12306.cnrn 
  3.  3Connection: keep-alivern 
  4.  4Content-Length: 55rn 
  5.  5Accept: application/json, text/javascript, */*; q=0.01rn 
  6.  6Origin: https://kyfw.12306.cnrn 
  7.  7X-Requested-With: XMLHttpRequestrn 
  8.  8User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36rn 
  9.  9Content-Type: application/x-www-form-urlencoded; charset=UTF-8rn 
  10. 10Referer: https://kyfw.12306.cn/otn/login/initrn 
  11. 11Accept-Encoding: gzip, deflate, brrn 
  12. 12Accept-Language: zh-CN,zh;q=0.9,en;q=0.8rn 
  13. 13Cookie: _passport_session=0b2cc5b86eb74bcc976bfa9dfef3e8a20712; _passport_ct=18d19b0930954d76b8057c732ce4cdcat8137; route=6f50b51faa11b987e576cdb301e545c4; RAIL_EXPIRATION=1526718782244; RAIL_DEVICEID=QuRAhOyIWv9lwWEhkq03x5Yl_livKZxx7gW6_-52oTZQda1c4zmVWxdw5Zk79xSDFHe9LJ57F8luYOFp_yahxDXQAOmEV8U1VgXavacuM2UPCFy3knfn42yTsJM3EYOy-hwpsP-jTb2OXevJj5acf40XsvsPDcM7; BIGipServerpool_passport=300745226.50215.0000; BIGipServerotn=1257243146.38945.0000; BIGipServerpassport=1005060362.50215.0000rn 
  14. 14rn 
  15. 15username=balloonwj%40qq.com&password=iloveyou&appid=otn 

其中username=balloonwj%40qq.com&password=iloveyou&appid=otn就是我们的POST数据,但是大家需要注意的以下几种,不要搞错:

1. 我的用户名是balloonwj@qq.com,到POST里面变成balloonwj%40qq.com,其中%40是@符号的16进制转码形式。这个码表可以参考这里:http://www.w3school.com.cn/tags/html_ref_urlencode.html

2.这里有三个变量,分别是username、password和appid,他们之间使用&符号分割,但是请注意的是,这不意味着传递多个POST变量时必须使用&符号分割,只不过这里是浏览器html表单(输入用户名和密码的文本框是html表单的一种)分割多个变量采用的默认方式而已。你可以根据你的需求,来自由定制,只要让服务器知道你的解析方式即可。比如可以这么分割:

方法一

  1. username=balloonwj%40qq.com|password=iloveyou|appid=otn 

方法二

  1. username:balloonwj%40qq.comrn 
  2. 2password:iloveyourn 
  3. 3appid:otnrn 

方法三

  1. username,password,appid=balloonwj%40qq.com,iloveyou,otn 

不管怎么分割,只要你能自己按一定的规则解析出来就可以了。

不知道你注意到没有,上面的POST数据放在http包体中,服务器如何解析呢?可能你没明白我的意思,看下图:

从零实现一个Http服务器

如上图所示,由于http协议是基于tcp协议的,tcp协议是流式协议,包头部分可以通过多出的rn来分界,包体部分如何分界呢?这是协议本身要解决的问题。目前一般有两种方式,第一种方式就是在包头中有个content-Length字段,这个字段的值的大小标识了POST数据的长度,上图中55就是数据username=balloonwj%40qq.com&password=iloveyou&appid=otn的长度,服务器收到一个数据包后,先从包头解析出这个字段的值,再根据这个值去读取相应长度的作为http协议的包体数据。还有一个格式叫做http chunked技术(分块),大致意思是将大包分成小包,具体的详情有兴趣的读者可以自行搜索学习。

三、http客户端实现

如果您能掌握以上说的http协议,你就可以自己通过代码组装http协议发送http请求了(也是各种开源http库的做法)。我们先简单地介绍一下如何模拟发送http。举个例子,我们要请求http://www.hootina.org/index_2013.php,那么我们可以先通过域名得到ip地址,即通过socket API gethostbyname()得到www.hootina.org的ip地址,由于http服务器默认的端口号是80,有了域名和ip地址之后,我们使用socket API connect()去连接服务器,然后根据上面介绍的格式组装成http协议包,利用socket API send()函数发出去,如果服务器有应答,我们可以使用socket API recv()去接受数据,接下来就是解析数据(先解析包头和包体)。

四、http服务器实现

(编辑:好传媒网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读