1.TCP的特点
面向连接的,端到端的,提供高可靠性服务
面向数据(字节)流
虚电路连接 类似于打电话
有缓冲的传输 发送方和接受方都有一个固定大小的缓冲空间
无结构的数据流
全双工连接
可靠性 :
1)防丢失:确认与重传
2)防重复:报文段序号
3)防乱序:报文段序号
传输效率
---------》滑动窗口机制
流量控制
拥塞控制 : 加速递减与慢启动
建立连接 三次握手协议
关闭连接 ---------->改进的三次握手协议
TCP建立连接
1)客户端发送SYN(synchronization)报文段——》指明连接的端口和初始序号ISN(seq=x)
2)服务器端接收到SYN报文后,发送ACK x+1 来告诉发送方已接收到第一个SYN 报文(确认号为x+1,表示期望接收的下一个报文段),发送SYN seq=y
3)客户端接收到 服务器的SYN 发送ACK y+1 告诉服务器接收到了SYN,通知服务器可以建立这个双方同意的连接
三次握手完成的三个功能
1>同意建立连接,确保双方做好传输数据的准备
2>协商各自报文段的初始序号ISN(ISN是随机选择的)
3>协商最大报文段长度(Maximum Segment Size ,MSS),只有SYN报文段才能协商该参数
问题,ISN一开始统一选取比如1这样的确认值不是更方便?
一个原因是IP欺骗
TCP连接正常关闭
1> 进行关闭的一端在发送完所有的数据并等待确认全部到达后,发送一个FIN seq = x来执行主动关闭(单方面的告诉你我不发东西了)
2>另一方收到FIN后,回一个ACK(我知道了),ACK seq = x+1 , (关闭读通道)
3>客户机收到ACK ,关闭写通道
《此时客户端仍能通过读通道读取服务器数据,服务端仍能写通道写数据》
《《《《《半关闭(half-close)》》》》,服务端可以继续发数据,客户端可以接收,回ACK
11>服务端发送FIN给客户端 (单方面告诉你我发完了,不发了)
22>客户端收到FIN后,回一个ACK ,(关闭客户端读通道),
33>服务端收到ACK后,关闭写通道
简单说来是 “先关读,后关写”,一共需要四个阶段。以客户机发起关闭连接为例:
第一次交互
1.服务器读通道关闭
2.客户机写通道关闭
第二次交互
3.客户机读通道关闭
4.服务器写通道关闭
------------------------------------------------------------------------------------------------------------------------------
与UDP类似,TCP允许多个应用进行通信,为了标志每个链接,TCP采用一对端点,<host,port>,主机IP地址,TCP端口号
怎么能防止数据丢失?
最好的办法莫过于收到数据后给一个ACK,收到了ACK再继续发送,如果一段时间没有接收到ACK,我觉得可能收不到了,直接重传
《带重传的肯定确认》
问题来了,该到的在指定时间内没有到,我重新发送了,但是突然又迷一般的到了,这下收到了重复的包,尴尬
肿么办?
TCP给每个报文段进行了编号,每个给了一个唯一的序号,通过序号我可以知道是否重复,丢掉一个重复的就行了,乱序也顺便就解决了,TCP没有规定乱序到达的数据报怎么处理,一般是放在缓冲区,等待他变成正序吧
编号方法:
n+1个报文的序号 = n + 第n个报文段的长度(正对于字节)
确认机制也就顺理成章了:
1)TCP确认指明的是下一个报文段的序号,收到了1024,报文长100 ,下一个是1124,ACK指明为1124
2)累计确认
ACK指明的是期望的下一个包,这样的好处是什么,比如接收到1024,在发回确认之前又收到了1124,这下直接省了一个ACK,返回一个1324 ACK就行了,这个还有一个特别好的东西,就是不一定会产生重传,接收到1024,返回1124,然后收到1224,返回1324,即使1124丢了,发送方也知道接受方收到了1024,
缺点是不能知道具体哪个报文段确认信息,只能知道数据流的位置,有时候对重传超时定时器的设置产生影响