计算机技术实战

纸上得来终觉浅,绝知此事要躬行。

Download this project as a .zip file Download this project as a tar.gz file

TCP

特点

TCP报文段首部格式

序号:己方发送的数据的第1个字节的编号。

确认号:期望接收对方下一条报文的第1个字节编号。

数据偏移

占4位,能够表示的范围是0-15,以4字节为单位,最大偏移60字节,也就是TCP首部的最大长度是60字节。

保留

6位,置0。

Urgent

紧急标志。

ACK

除3次握手的第一次握手ACK标志为0,其他情况下ACK均为1。

Push

接收方收到之后尽快交给应用进程,而不再等到整个缓冲区都填满。

Reset

复位。

Syn

同步,建立连接时使用。

Fin

终止,释放连接时使用。

检验和

12字节伪首部+TCP首部+数据。例如:

计算方法为:

        long result = ChecksumUtils.getCheckSum(new int[]{
                // 12字节伪首部
                0xc0a8,//源ip前半部分:192.168
                0x0069,//源ip后半部分:0.105
                0xc0a8,//目标ip前半部分:192.168
                0x0065,//目标ip后半部分:0.101
                0x0006,//定值,指TCP协议号
                37, //tcp长度
                // 12字节伪首部 end

                // tcp 首部
                0xe240,// 源端口
                0x07e2,// 目标端口
                0x8b63,
                0x86f0,
                0x1763,
                0x7266,
                0x8018,
                0x1015,
                0x0000,// 检验和初始值0
                0x0000,
                0x0101,
                0x080a,
                0x01ad,
                0x6b83,
                0x006f,
                0xd12d,
                // tcp 首部 end

                0x6162,//数据
                0x6320,//数据
                0x0a00,//数据
        });
public class ChecksumUtils {
    /**
     * 反码获取检验和
     * 参考:https://baike.baidu.com/item/%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%8F%8D%E7%A0%81%E6%B1%82%E5%92%8C/10462750?fr=aladdin
     *
     * @return
     */
    public static int getCheckSum(int[] data) {
        int sum = 0;
        int n = data.length;
        for (int i = 0; i < n; i++) {
            sum += data[i];
            sum = (sum >> 16) + (sum & 0xffff);
        }
        sum = ~sum;
        sum = sum & 0xffff;
        return sum;
    }
}

可靠传输的工作原理

停止等待协议

每发送完一个分组就停止发送,等待对方确认,在收到确认后再发送下一个分组。如果分组传输过程中丢失或者出现差错,对方不会发送确认,发送方超过一段时间没有收到确认,就认为刚刚发送的分组丢失,于是重传刚刚的分组,即超时重传。停止等待协议效率低,实际上基本不用。

连续ARQ(Automatic Repeat reQuest)协议