图2-2 TCP头
1、源端口和目的端口字段标识出本地和远端的连接点。每个主机都可以自行决定如何分配自己的端口(从256开始)。
2、顺序号和确认号字段执行它的通用功能。确认号指希望接收下一个字节而不是前面已经正确接收的字节。
3、TCP头长表明在TCP头中包含多少个32位字。由于可选项字段是变长的,因此TCP头也是变长的,它实际上是指明了数据在数据段中的开始位置。接下来有6个未用的位。
4、接下来是六个1位的标志:
(1)URG位是应急指针标志,当用到了应急指针,则URG置1。应急指针指从当前顺序号到紧急数据位置的偏移量。
(2)ACK位置1表明确认号是合法的。ACK为0表示数据段不包括确认信息。
(3)PSH伪表示是带有PUSH位标志的数据。
(4)RST位用于复位由于主机崩溃或其他原因而出现错误的连接。
(5)SYN位用于建立连接。在连接请求中,SYN=1,ACK=0,表示捎带确认字段无效。连接响应数据段应带有确认,因此SYN=1,ACK=1。
(6)FIN位用于释放连接,它表明发送方已经没有数据发送了,然而当断开连接后,进程还可以继续接收数据。
5、窗口大小字段表示在确认了字节之后还可以发送多个字节,由于TCP中的流量控制是通过滑动窗口来处理的。窗口大小为0也是合法的,表示它已经收到了包括当前字段的所有数据段,但当前接收方急需暂停,希望不要发数据。
6、校验和也是为了确保高可靠性而设置的。它校验头部,数据和伪IP头(如下图)之和。当接收方对整个数据段,包括校验和字段进行运算时,结果应是0。
一个人要能够收到别人打给他的电话,首先他要装上一门电话。同样,必须先建立 socket 以侦听线路。这个过程包含几个步骤。首先,要建立一个新的 socket,就像先装上电话一样。socket() 命令就完成这个工作。
因为 sockets 有几种类型,因此要注明我们要建立什么类型的。我们要做一个选择是 socket 的地址格式。如同电话有音频和脉冲两种形式一样,socket 有两个最重要的选项是 AF_UNIX 和 AF_INET。我们这里将着重于 AF_INET 方式。AF_INET 使用202.117.1.13 这样被点号隔开的四个十进制数字的地址格式。除了机器地址以外,还可以利用端口号允许每台机器上的多个 AF_INET socket。
另外一个必须提供的参数是 socket 的类型。流式套接字提供了双向、有序的、无重复的以及无记录边界的数据流服务,适合处理大量数据。它是面向联结的,必须建立数据传输链路,同时还必须对传输的数据进行验证,确保数据的准确性。因此,系统开销较大。而数据报套接字也支持双向的数据流,但不保证传输数据的准确性,但保留了记录边界。由于数据报套接字是无联接的,例如广播时的联接,所以并不保证接收端是否正在侦听。数据报套接字传输效率比较高。SOCK_RAW是将套接字定义为原始套接字。原始套接字保存了数据包中的完整IP头,前面两种套接字只能收到用户数据。因此可以通过原始套接字对数据进行分析。
在建立 socket 后,我们就要提供 socket 侦听的地址了。bind() 函数来处理这件事情,将本地地址绑定到所创建的套接字上。然后我们要做的就是设置 SOCK_RAW 为SIO_RCVALL,以便接收所有的IP包。这里的SIO_RCVALL是指示SOCK_RAW接收所有的数据包。
前面的工作基本上都是对原始套接字进行设置,在将原始套接字设置完毕,使其能按预期目的工作时,就可以通过recv()函数从网卡接收数据了,接收到的原始数据包存放在缓存RecvBuf[]中,缓冲区长度BUFFER_SIZE定义为65535。然后就可以根据前面对IP数据段头、TCP数据段头的结构描述而对捕获的数据包进行分析。
定义一个名为ip的指针,指向IP头的第一个位,定义一个名为tcp的指针指向地址=(IP头的首地址+IP头的长度)的位置。这两个指针的定义分别定义了IP头和TCP头。然后在IP头分析Protocol,如果满足上述定义的TCP头,UDP头的情况,利用函数GetProtocolTxt()分别输出“TCP”“UDP”。
将buf清0,得到一个16位的空栈,然后将ip指针分别指向src_addr[0],src_addr[1], src_addr[2] ,src_addr[3],彼此之间用“.”间隔开,得到数据包的源地址。同样的,将ip指向tar_addr[0],tar_addr[1],tar_addr[2],tar_addr[3],用“.”间隔开,得到数据包的目的地址。然后在分别由src_port,dest_port,datalen分别读出数据包的源端口,目的端口,和数据包长度。Datalen由length[0]× +length[1]。
最后,将该程序进行测试,该程序已经具备了网络流量测量的基本功能:捕获数据包,对数据包进行IP层以上的分析。