tcp、http 学习小结

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头部格式
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-seq

syn/ack:
这里写图片描述

ack:
这里写图片描述

步骤flags标志位seq numberack numbertsvaltsecr
syn0x002ack=10x92 0x68 0xa8 0x5305829718790
syn/ack0x012ack=1,syn=10xb2 0x29 0xde 0x5b0x92 0x68 0xa8 0x54776961681582971879
ack0x010ack=10x92 0x68 0xa8 0x540xb2 0x29 0xde 0x5c582971887776961681

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

类似的结束时候

步骤flags标志位seq numberack numbertsvaltsecr
fin/ack0x011fin=1,ack=10xb2 0x29 0xe4 0x680x92 0x68 0xa8 0x99776961691582971887
ack0x010ack=10x92 0x68 0xa8 0x990xb2 0x29 0xe4 0x69582971898776961691
fin/ack0x011fin=1,ack=10x92 0x68 0xa8 0x990xb2 0x29 0xe4 0x69582971898776961691
ack0x010ack=10xb2 0x29 0xe4 0x690x92 0x68 0xa8 0x9a776961720582971898

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

tcp option头部

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值