tcp、http 学习小结

前言

最近因为cdn的一个问题,困扰了自己好久。因为需要统计网站访问的成功数,而且要求比较精确。目前的实现不能满足要求,因为没有区别访问成功与否,也没有对超时做处理。期间解决这个问题,走了不少弯路,现在在这里记录下来,为自己也为别人提供一个方便。

关键字

  • tcp
  • 1.tcp三次握手
  • 2.tcp序列号,确认号
  • 3.tcp 头部扩展option域
  • http
  • 1.http 1.0与http1.1
  • 2.get,response
  • 3.http 返回码
  • wireshark
  • 工具介绍

一.tcp小结

tcp头格式:



tcp结构体struct tcphdr

struct tcphdr {
__u16 source;
__u16 dest;
__u32 seq;
__u32 ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 res1:4,
doff:4,
fin:1,
syn:1,
rst:1,
psh:1,
ack:1,
urg:1,
ece:1,
cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 doff:4,
res1:4,
cwr:1,
ece:1,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__u16 window;
__u16 check;
__u16 urg_ptr;
};

tcp建立连接与关闭连接

tcp建立连接需要经过三次握手syn->syn/ack->ack,三次握手每一步都是必需的,在网络环境比较差的时候,会发生握手包丢失,tcp会自动重复发送握手包,直到连接建立或者超时。

tcp建立连接时候的初始序列号并不是0,而是经过一种算法得到的,具体百度。这可以保证tcp序列号不至于错乱,在wireshark中显示的序列号是相对序列号,wireshark把每次syn的序列号作为基准0,这样的目的是看起来更直观。

syn:

syn/ack:

ack:

步骤 flags 标志位 seq number ack number tsval tsecr
syn 0x002 ack=1 0x92 0x68 0xa8 0x53 0 582971879 0
syn/ack 0x012 ack=1,syn=1 0xb2 0x29 0xde 0x5b 0x92 0x68 0xa8 0x54 776961681 582971879
ack 0x010 ack=1 0x92 0x68 0xa8 0x54 0xb2 0x29 0xde 0x5c 582971887 776961681

可以看出来初始序列号并不是0,每次的确认号表示的是期望下次从对方收到的序列号的值。序列号与确认号都是uint32_t类型,占据32位,达到最大又会从0开始。

类似的结束时候

步骤 flags 标志位 seq number ack number tsval tsecr
fin/ack 0x011 fin=1,ack=1 0xb2 0x29 0xe4 0x68 0x92 0x68 0xa8 0x99 776961691 582971887
ack 0x010 ack=1 0x92 0x68 0xa8 0x99 0xb2 0x29 0xe4 0x69 582971898 776961691
fin/ack 0x011 fin=1,ack=1 0x92 0x68 0xa8 0x99 0xb2 0x29 0xe4 0x69 582971898 776961691
ack 0x010 ack=1 0xb2 0x29 0xe4 0x69 0x92 0x68 0xa8 0x9a 776961720 582971898

tcp关闭连接是经过四次握手,建立连接经过三次握手,值得提出的是建立和关闭连接并不消耗序列号,只有成功建立或者关闭序列号才会加一,具体可以自己抓包分析下。

tcp option头部

上面的tsval,与tsecr是在tcp头部的扩展字段(kind)。本身并不包含于tcphdr结构体中,因为这是由后续rfc文档建议添加的字段,在tcp模块编写之后提出的。因为tcp option的存在,所以tcp头的长度一般不是20(tcp->doff == 4),tcp头最小是20bytes。

下面是kind字段意义列表:

Kind Meaning Reference
0 End of Option List [RFC793]
1 No-Operation [RFC793]
2 Maximum Segment Size [RFC793]
3 WSOPT - Window Scale [RFC1323]
4 SACK Permitted [RFC2018]
5 SACK [RFC2018]
6 Echo (obsoleted by option 8) [RFC1072]
7 Echo Reply (obsoleted by option 8) [RFC1072]
8 TSOPT - Time Stamp Option [RFC1323]
9 Partial Order Connection Permitted [RFC1693]
10 Partial Order Service Profile [RFC1693]
11 CC [RFC1644]
12 CC.NEW [RFC1644]
13 CC.ECHO [RFC1644]
14 TCP Alternate Checksum Request [RFC1146]
15 TCP Alternate Checksum Data [RFC1146]
16 Skeeter [Knowles]
17 Bubba [Knowles]
18 Trailer Checksum Option [Subbu & Monroe]
19 MD5 Signature Option [RFC2385]
20 SCPS Capabilities [Scott]
21 Selective Negative Acknowledgements [Scott]
22 Record Boundaries [Scott]
23 Corruption experienced [Scott]
24 SNAP [Sukonnik]
25 Unassigned (released 12/18/00)
26 TCP Compression Filter [Bellovin]

其中我用到的是kind为8的字段,意思是在每个数据包上加上tcp时间戳。时间戳分为tsval与tsecr两个,分别由连接的两端进行维护,每次传输时需要在tsecr上对对方上次的数据包的时间戳进行确认,并在tsval加上自己最新的时间戳。

tcp时间戳并不是系统时间,通过date -d @776961691可以看到结果是Mon Aug 15 22:41:31 CST 1994,时间明显不对。tcp时间戳不采取系统时间的理由也很充分,每次同步时间都会导致时间突变,这就会导致时间戳也突变,这是不可取的。实际上tcp采用的是系统从开机以来的相对时间,这样只要不关机,就不会变化。系统默认每次HZ是250,这是在内核编译时指定的,也就是jiffies每增加一就是4ms的时间。因此可以通过两次tsval时间差计算出两次发包的时间间隔。

http://blog.csdn.net/zhandoushi1982/article/details/5536210

http

http是应用层协议,一般是建立在tcp之上的。也就是说http是面向用户,并不关心底层连接的实现。有句话叫做“http面向连接的,但是是无状态的”。这句话可以这么理解:基于tcp实现的http,每次发送请求都会先建立tcp连接,在连接建立之后发送http数据。然而http又是无记忆的,http并不知道自己已经发送过哪些数据,所以对于同样的请求,比如每次打开www.baidu.com,刷新页面都是重新发送的数据。http把这当作一次新的请求。

http数据是紧挨着tcp头之后的。

一个完整的包结构是这样的:

-{Ethernet | Ip | tcp/udp | HTTP}

http现在最流行的是http 1.1版本,相比于之前版本,效率提高了许多。http 1.0是短连接,每次传输数据会建立一个tcp连接,使用完毕立马关闭,下次使用重新建立连接。http 1.1则默认长连接,这在http头域connection选项中可以设置,值为close为短连接,keep-alive为长连接。

验证如下:

telnet www.baidu.com 80

输入:

GET / HTTP/1.1

两次回车,(这是因为http规定行末,以及头结束必须为\r\n)

GET / HTTP/1.0

http 1.0



http 1.1

先写这么多。。。

参考链接给在下面,懒得写了

http://blog.chinaunix.net/uid-8059407-id-2034302.html

http://www.cse.scu.edu/~dclark/am_256_graph_theory/linux_2_6_stack/linux_2tcp_8h-source.html

http://blog.csdn.net/mrwangwang/article/details/8537775

http://blog.csdn.net/zhandoushi1982/article/details/5536210

最新文章

  1. WPFTookit Chart 入门
  2. oracle 配置监听 windows下 oracle 12c
  3. hadoop安装及配置入门篇
  4. Tomcat内存优化参数
  5. mvc4 部署http错误403.14 forbidden
  6. listbox 报错 Cannot have multiple items selected when the SelectionMode is Single.
  7. pymongo 3.3 使用笔记
  8. datagrid动态数据添加超链接的方法
  9. 【转载】为什么CPU有多层缓存
  10. Apache Struts 跨站脚本漏洞
  11. 经常使用的两个清爽的table样式
  12. PyCharm 4.0下载(附keygen)
  13. ASP无惧上传类不能上传中文双引号文件及ASP函数InStr存在bug
  14. 蚂蚁金服ATEC城市峰会上海举行,三大发布迎接金融科技2019
  15. CSS第二篇
  16. 大数据技术 - MapReduce的Shuffle及调优
  17. zabbix4.0下zabbix-agentd安装
  18. kmp--看毛片算法
  19. ThinkPad 复刻计划 ThinkPad Time Machine
  20. Oracle创建库

热门文章

  1. 学长小清新题表之UOJ 180.实验室外的攻防战
  2. CSS3动画旋转——(图片360&#176;旋转)
  3. python re之search/match差别
  4. 细讲前端设置cookie, 储存用户登录信息
  5. Jmeter 常用函数(26)- 详解 __chooseRandom
  6. sge的简单的应用
  7. 记录一次CDH集群邮件报警功能的设置
  8. MPI自定义数据类型
  9. 面经手册 &#183; 第7篇《ArrayList也这么多知识?一个指定位置插入就把谢飞机面晕了!》
  10. win10安装JDK cmd中可以运行java,但不能用javac,解决方案