网络协议栈6:connect()函数之前之TCP

从connect开始,就涉及到各种各样的协议了,目前先把TCP/IP协议理清。

首先,先把TCP(transmit control protocol, 传输控制协议)的结构图跟结构体对上:

  

 

#define HEADER_SIZE 64      /* maximum header size      */

 

struct tcphdr {/*tcp头部*/

/*

发送端端口号:16 比特

标识该数据包源端数据发送进程。

*/

    __u16   source;

/*

目的端端口号:16 比特

标识该数据包目的端数据接收进程。

*/

    __u16   dest;

/*

序列号:32比特

本端发送的数据包中所包含数据的第一个字节的序列号。

*/

    __u32   seq;

/*

应答序列号:32 比特

该序列号表示本端想要接收的的下一个数据包中所包含数据中第一个字节数据的序列号。

注意不要混淆序列号和应答序列号这两个字段的意义。序列号字段是对本地发送数据的编

号, 而应答序列号是对对方发送数据的计号: 即计算本地已接收到的对方发送的数据的编号。

*/

    __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,

        res2:2;

#elif defined(BIG_ENDIAN_BITFIELD)

/*

数据偏移:4比特

该字段表示 TCP 首部以 4 字节为单位的长度(包括 TCP 选项,如果存在) 。换句话说即用

户数据的开始起点(从 TCP 首部第一个字节算起) 。由此可见如同 IP 首部,TCP 首部必是

4 字节的整数倍,有时这需要在首部结尾处加填充字节。

*/

    __u16   doff:4,

/*

保留字段:6比特 (4+2=6)

必须初始化为 0。

*/ 

        res1:4,

        res2:2,

/*

控制位:6 比特

URG:URG=1 表示紧急指针字段值有效,否则无效。紧急数据是将接收的数据迅速传替给

应用程序的一种手段。

ACK:ACK=1 表示这是一个应答报文(注意应答报文中可以包含本端发送的数据,事实上,

很少只发送一个应答报文而其中不附带数据的,换句话说,应答报文一般都是随数据

顺便发送的。

PSH:PSH=1 时的意义如同 URG=1 表示需要将数据立刻交给应用程序。软件处理上是给应

用程序发送信号(SIGURG) 。

RST:复位标志。当一个报文中 RST=1 时,表示对方要求本地重新建立与对方的连接。该

标志位一般用于非严重错误恢复中。

SYN:同步标志。当SYN=1 时表示这是一个同步报文,同步报文只用在建立连接的过程中。 

FIN:结束连接报文。当 FIN=1 时表示本地已无数据发送给对端,但可以继续接收对方发送

的数据。FIN报文通常使用在关闭连接中。

*/     

        urg:1,

        ack:1,

        psh:1,

        rst:1,

        syn:1,

        fin:1;

#else

#error  "Adjust your <asm/byteorder.h> defines"

#endif 

/*

窗口大小:16 比特

该字段用于流量节制:表示当前对方所能容忍的最大数据接收量。本地必须注意到该要求, 

发送的数据量必须小于该字段所声明的值。

*/

    __u16   window;

/*

校验和:16比特

该字段计算 TCP首部及其之后的所有用户数据部分的校验和。

注意在计算 TCP校验和(UDP 也如此)还包含一个伪首部的计算。图 1-31 显示了计算 TCP

校验和时所需计入的伪首部格式。

*/

    __u16   check;

/*

紧急指针:16 比特

该字段表示紧急数据部分,其值是一个偏移量,该偏移量是从该数据包中第一个数据字节

算起。只当 URG标志位为 1 时,紧急指针字段值方才有效。

*/

    __u16   urg_ptr;

};

 

/*TCP连接可能的状态

*/

enum {

  TCP_ESTABLISHED = 1,/*代表一个打开的连接*/

  TCP_SYN_SENT,/*再发送连接请求后等待匹配的连接请求*/

  TCP_SYN_RECV,/*再收到和发送一个连接请求后等待对方对连接请求的确认*/

  TCP_FIN_WAIT1,/*等待远程TCP连接中断请求,或先前的连接中断请求的确认*/

  TCP_FIN_WAIT2,/*从远程TCP等待连接中断请求*/

  TCP_TIME_WAIT,/*等待足够的时间以确保远程TCP接收到连接中断请求的确认*/

  TCP_CLOSE,/*没有任何连接状态*/

  TCP_CLOSE_WAIT,/*等待从本地用户发来的连接中断请求*/

  TCP_LAST_ACK,/*等待原来的发向远程TCP的连接中断请求的确认*/

  TCP_LISTEN,/*侦听来自远方的TCP端口的连接请求*/

  TCP_CLOSING   /* now a valid state 等待远程TCP对连接中断的确认*/

};

TCP首部记录的是数据包的一些附带的说明信息,而不是信息的本身,主要包括数据包的双方端口号(此时的远端端口号还是初始化为0),发送的数据包的序号和期望的确认号,以及数据包的紧急性等,在路由上发送数据时,就可以经过对这些属性的分析,从而决定是先得到发送,还是稍后再发送,等等。

TCP首部信息,主要是为了保证发送数据的安全发送到远端,如果在发送数据之后,没有得到远端发回的收到数据的确认(即发送数据时有一个成员记录了发送数据的第一个字节的字节序,远端收到数据后要在这个字节序+1之后发送回来,表示已经收到了数据),即没有收到确认信号,就在等待一段时间后,再把没有收到远端确认的数据再次发送,而且这个再发送的数据的优先级最高,直到收到远端收到数据的确认信号为止。

通过把这些信息附带以TCP的数据格式附带在数据包上,等数据传输到远端的机器后,数据被传输到TCP层时,就是按照这个数据包的TCP头部的信息来解析这个包,根据分析的结果来决定下步怎么走。

posted on 2012-01-07 15:38  image eye  阅读(1193)  评论(0编辑  收藏  举报