1 - 协议栈概述
2 - TCP协议
TCP: 传输控制协议. 是一种面向连接的可靠的流协议.

2.1 - TCP握手过程
TCP第一个特性就是面向连接. 顾名思义, 两端在通信之前必须建立一条通信通道.
2.1.1 - 三次握手

SYN段: TCP协议中的标志位. 表示主机A发送的是要建立连接的请求.
1和2: 称为一个RTT(Round-Trip Time).
2.1.2 - 四次挥手

- FIN: TCP协议中的标志位. 表示要断开TCP连接
- 一般情况下2和3会同时发送到主机A
2.2 - TCP如何可靠传输
2.2.1 - 序列号和确认应答
2.2.2 - 超时重传
2.2.3 - 连接管理
2.2.4 - 窗口控制
2.3 - TCP粘包断包
2.3.1 - 什么是粘包断包
接收方收到的数据包, 并不是发送方的完整数据. 不足一条完整数据包时叫做断包, 超过完整数据包长度的叫做粘包
2.3.2 - 产生原因
- MTU/MSS
- TCP拥塞算法
- 发送缓冲区
2.3.3 - 如何解决
TCP/IP协议本身无法理解上层数据语义, 那么上层应用在设计数据协议的时候, 就需要保证数据的有界. 一般有两种解决方案.
- 定长Header + 不定长Body
无意义分隔符


public boolean doDecode(IoSession iosession, IoBuffer iobuffer, ProtocolDecoderOutput out) throws Exception {boolean complete = false;IoBuffer buff = IoBuffer.allocate(320).setAutoExpand(true);while (iobuffer.hasRemaining()) {byte b = iobuffer.get();if (b == CIMConstant.MESSAGE_SEPARATE) {complete = true;break;}buff.put(b);}buff.flip();byte[] bytes = new byte[buff.limit()];buff.get(bytes);String message = new String(bytes, charset);if (!complete) {int position = iobuffer.position();int limit = iobuffer.limit();logger.warn("消息不够消费, {} => :: 当前位置 => {} :: 长度 => {} ", message, position, limit);iobuffer.flip();return false;}buff.clear();// message解析成高级对象}
IoBuffer resultBuffer = null;do {byte frameInfo = in.get();// 第一个byte抹掉高4位 取opcodebyte opCode = (byte) (frameInfo & 0x0f);if (opCode == 8) {// opCode = 8 关闭连接session.closeNow();return resultBuffer;}// 第二个byte抹掉第1位 取有效数据长度 PlayLoad length// PlayLoad length < 126: 真实数据长度// PlayLoad length = 126: 紧跟着后2个字节代表数据长度// PlayLoad length = 127: 紧跟着后8个字节代表数据长度int frameLen = (in.get() & (byte) 0x7F);if (frameLen == 126) {frameLen = in.getShort();}// 缓冲区的数据不足if (frameLen + 4 > in.remaining()) {return null;}// PlayLoad length后面的是4byte的masking-keybyte mask[] = new byte[4];for (int i = 0; i < 4; i++) {mask[i] = in.get();}byte[] unMaskedPayLoad = new byte[frameLen];for (int i = 0; i < frameLen; i++) {byte maskedByte = in.get();unMaskedPayLoad[i] = (byte) (maskedByte ^ mask[i % 4]);}if (resultBuffer == null) {resultBuffer = IoBuffer.wrap(unMaskedPayLoad);resultBuffer.position(resultBuffer.limit());resultBuffer.setAutoExpand(true);} else {resultBuffer.put(unMaskedPayLoad);}}while (in.hasRemaining());resultBuffer.flip();
3 - TCP状态转换


如果服务端存在大量出于TIME_WAIT状态的连接, 可能会带来:
- 服务端进程关闭后, 可能会在一段时间内无法重启
- 大量TIME_WAIT堆积, 如果超出了服务器可分配的端口范围, 会导致无法创建新的连接
