推荐查看:http://www.cocoachina.com/programmer/20170316/18895.html
https://blog.csdn.net/qzcsu/article/details/72861891
一个 TCP Header 一般有 20 个字节,如果启用了 options,header的长度可以达到 60 个字节。上图中每一行是 4 个 bytes,32 个 bits。我先带大家学习下前 5 行,每一行是 4 Bytes,五行刚好是 20 个 bytes。计算机世界中,通常会以 bit,byte,word(4 个 byte)等不同粒度来描述信息,header 的学习一般是以 4 个字节为一个单位来展示的。
-
第一行,由 Source port 和 Destination port 构成,二者各占 2 个字节,刚好一起占据第一行的 4 个字节。这两个字段分别表示 TCP 连接中的,发送方端口号和接收方的端口号,既然一个 port 只占 2 个 bytes,那么端口值的范围自然就是 0~65535 啦。
-
第二行,Sequence number,表示发送方的序列号。这个序列号表示的是什么呢?一个 TCP 流是有无数个 0 和 1 构成,这些 0 和 1 以 8 个 bit 为单位,可以分割成一个个的 byte,TCP 是可靠传输协议,每一个 byte 都是有标号的,因为我们需要追踪每个 byte 是否被成功传输了,每个 byte 的标号就是我们这里的 sequence number。假设我们建立 TCP 连接的时候,发一个 sync 包,我们就以 0 标记 sync 包的第一个字节,那么 sync 包中的 Sequence 值就是 0。实际应用中,处于安全考虑,TCP 流的第一个 Sequence number 一般不会是 0,而是一个随机数。Sequence number 占据 4 个字节,也就是 2 的 32 次方,这个数字并不算大,每个包都会用掉一些,如果达到最大值之后,就取余从 0 重新开始。
-
第三行,Acknowledge number,表示接收方 ack 的序列号。接收方收到发送方一个的 TCP 包之后,取出其中的 sequence number,在下一个接收方自己要发送的包中,设置 ack 比特位为 1,同时设置 acknowledge number 为 sequence number + 1。所以接收方的 acknowledge number 表示的是,接收方期待接收的下一个包起始字节的标号,大家可以仔细理解下这一句话。所以 acknowledge number 和 sequence number 是配对使用的。
-
第四行,这一行尤其重要,出于篇幅的考虑,其中细节会在后续的文章中讲解。这里简单提下从 CWR 到 FIN 的 8 个 bit,这 8 个 bit 里每一位都是一个标记位,用来标记当前 TCP 包的特殊含义。比如我们所说的三次握手,第一个 sync 包,就是将 SYN 位置为 1。第二个 syn + ack 包就是将 header 的 ACK 和 SYN 位都置为 1。第三个 ack 包即将 ACK 位置 1。剩余的几个 bit 位暂时不展开讲了,大家可以自己看书先学习下。
-
第五行,这一行只有两个字段,即 Checksum 和 Urgent pointer。checksum 是个通用的计算机概念,做完整性校验之用,在很多协议(IP,UDP,ICMP)中都有应用,这个值有包的发送方去计算,之后由包的接收方取出来校验。Urgent pointer 为两个字节的偏移量,加上当前包的 sequence number,用来标记某一个范围内的 bytes 为特殊用途数据。
-
package: DDDataOutputStream *dataout = [[DDDataOutputStreamalloc] init];//outPutStream 写入流为了传给服务器信息 相对的,对服务器而言outputStream 是输出流,inputStream是输入流
[dataout writeInt:0];//从0开始写
[dataout writeTcpProtocolHeader:SID_GROUP //Source port发送方的端口号
cId:CID_GROUP_EXIT_GROUP_REQUEST//Destination port 接收方的端口号
seqNo:seqNo];//seqNo 发送方的序列号
[dataout directWriteBytes:[getCodebuild].data];
[dataout writeDataCount];
return [dataouttoByteArray];
Analysis analysis = (id)^(NSData* data)//这是接收方方通过 acknowledge number 和 sequence number 配对识别下发给我的数据
{
IMGroupExitGroupRsp *res = [IMGroupExitGroupRspparseFromData:data];//这个是服务器通过下发给我的数据
NSMutableArray *resultArr = [[NSMutableArrayalloc] init];//inputStream 输出流这是服务器响应下发给我的数据
// NSMutableArray *userList = [[NSMutableArray alloc] init];
// IMUint64List *list = res.memberlist;
//
// userList = [list itemList].mutableCopy;
[resultArr addObject:@(res.resultCode)];
[resultArr addObject:@(res.userId)];
[resultArr addObject:@(res.groupId)];
// [resultArr addObject:@(res.groupmsgId)];
// [resultArr addObject:userList];
[resultArr addObject:res.info];
return resultArr;
};
return analysis;
结合代码以及理论TCP 连接的三次握手有更深沉次的体验