TCP与UDP

TCPUDP是基于IP协议的.

TCP与UDP为应用进程之间提供了逻辑通信. IP协议则为主机之间提供了逻辑通信.

IP协议的服务模型是尽力而为交付服务(best-effort delivery service).这就意味着IP尽力在通信的主机之间交付报文段,却不做任何担保. 它不保证报文段的交付,不保证报文段的按序交付,更不能保证报文段中数据的完整性.因此,IP协议被称为不可靠服务.

 

说到TCP与UDP,有几个特别重要的名词就不得不提了: 套接字(Socket), 运输层的多路复用(transport-layer multiplexing)与多路分解(demultiplexing).

套接字(Socket)

  作为操作系统的一套应用程序编程接口.(即进程用来网络通信,由操作系统提供的编程接口).应用程序可以通过套接字, 进行消息发送与接收.

运输层的多路复用

  从不同进程中收集数据块(进程通过Socket发送的数据),并为每个数据块封装上首部信息从而生成报文段,然后将报文段传递到网络层的工作称为多路复用.

多路分解

  将运输层报文段中的数据交付到正确的套接字(通过唯一标识: IP+端口号识别)的工作称为多路分解.

 

 

UDP

  轻量级传输协议. 只提供了基础的差错检测多路复用/多路分解功能.实际上,如果应用程序开发人员选择UDP,则应用程序几乎就直接与IP在打交道.

  UDP是无连接的.

  UDP的优势:

    应用层能更好的控制要发送的数据和发送时间.

    无需连接建立.

    无连接状态.

    分组首部开销小.

  UDP报文格式:

  

 

TCP

 TCP是可靠的运输协议. 它能确保一个进程从其接收缓存中读出非损坏的,无间隔的,无冗余的和按序的数据流.

 TCP是面向连接的. 两个应用进程在发送数据之前, 必须进行相互"握手"("三次握手", 即它们必须相互发送某些预备报文段, 以建立确保数据传输所需的参数.)

 TCP是全双工服务(full-duplex service).  如果一台主机的进程A与另一台主机的进程B存在一条TCP连接, 那么应用层数据就能从进程B流向进程A的同时, 也从进程A流向进程B. TCP连接也总是点对点(point-to-point)的.

 

 TCP报文结构.

  

  •  源端口号目标端口号就不用多说了, 和UDP一样, 用于多路复用/多路分解.
  •  序号 SEQ标识所传字节的序号. 用于保证数据的有序性. (与确认号都是可靠传输的重要角色)
  •  确认号 ACK, 用于告诉接收方已确认的数据序号.(讲白点,就是一句通知: "东西我已经收到了, 我希望你下次送我ACK序号的东西" )
  •  首部长度 由于TCP选项的原因, TCP首部长度是可变的.(一般为空, 所以一般TCP首部为20字节)
  •  6比特的标志字段

    ACK用于指示确认字段中的值时有效的.

    RST, SYNFIN比特用于连接的建立和拆除.

    PSH 表示接收放应立即将数据交给上层

    URG 指存在紧急数据. 与后面的紧急数据指针字段

  • 检验和 同UDP.

 

 

TCP连接的建立. 

  • 第一步: 客户机端TCP首先向服务器发送一个特殊的TCP报文段. 该报文SYN标识会被置为1. 且会生成一个起始序号client_isn, 将其放入报文的序号字段中. (client_isn的生成是有一定的学问的)
  • 第二步: 当SYN报文到达服务端时, 服务器会从该数据报中提取出TCP SYN报文段, 为该TCP连接分配TCP缓存和变量. 并向客户机TCP发送允许连接的报文段.   
  •             这个允许连接的报文段不包含应用层数据. 但SYN比特会被置为1, 且确认号被置为client_isn + 1. 最后服务器会生成自己的初始序号(server_isn), 并将其放置到TCP报文段首部的序号字段中. 这个连接报文段被称为 SYNACK报文段
  • 第三步: 在收到SYNACK报文段后, 客户机也要给该连接分配缓存和变量.客户端主机还会想服务器发送另外一个报文段, 这个报文段对服务器的允许连接的报文段进行了确认.
  •              (客户机将值server_isn+1放置到TCP报文首部的确认字段来完成此项工作). 因为连接已建立, 所以该SYN标志被置为0. (这个报文可以携带数据)

 

  

 

TCP可靠数据的传递机制.

  TCP利用几个特别的技术实现了可靠传输. 检验和, 重传, 定时器, 滑动窗口, 确认序号.

/** 发送方 **/
sendBase = client_isn,
nextSeqNum = client_isn,
MSS = 1460;
events = {
  "sendData": "应用程序发送数据",
  "timeout": "定时器超时",
  "acceptAck": "接收ack",
};
while (event.incoming()) {
  if (event == events.sendData) {
    // 不考虑流量控制的情况下.
    if ()
  }

  if (event == events.timeout) {
  }
  
  if (event == events.acceptAck) {}
}

 

牛逼的TCP交互动态程序

 TCP流量控制

  

 

posted @ 2017-01-20 10:43  君叶秋  阅读(296)  评论(0编辑  收藏  举报