【UNIX网络编程读书笔记】第二章 传输层 TCP/UDP

TCP是一个字节流(byte-stream)协议,没有任何记录边界,这一点不同于UDP

TCP三次握手(结合程序):

准备:
服务器passive open
服务器准备好接受外来的链接
调用socket(); bind(); listen()这三个函数完成

  1. 客户端active open
    调用connect()主动打开(发送一个SYN分节(没有数据,告诉发送数据的开始序列号));
  2. 服务器确认
    服务器确认(ACK)客户端的(SYN)这里应该就用到accept()了吧;
    然后发回去SYN,ACK
  3. 客户端确认
    客户端确认服务器的SYN( connect()函数产生返回值 ),先发送ACK,然后发送数据,
    服务端收到accept()函数的返回值,然后调用read()接受数据

TCP四次挥手(结合程序):

  1. 客户端active close
    调用close(),该端的TCP发送一个FIN分节,表示数据发送完毕。
  2. 服务器passsive close
    收到FIN( read()函数返回0 )由TCP确认(发回一个ACK)。他的接受也作为与一个文件结束符(EOF)传递给应用进程
  3. 服务器FIN
    接收到这个EOF的应用进程将调用close()关闭它的套接字,导致它的TCP也发出一个FIN信号
  4. 客户端确认
    客户端确认服务器的FIN

四次挥手可能成为三次,是因为2,3的ACK和FIN可能一起发送;

发送FIN是因为应用进程调用close()而发生的

序列号?

看到这里的时候发现有点混乱;
首先SYN和ACK是报文首部的内容;

ACK告诉对端自己期待接收到的下一个包的序列号,通常为最近收到的包的序列号 + 1

三次握手的时候:
第一次客户端向服务端发送的报文里的SYN标志位为1(标识该报文用来建立连接),整个包的序列号为client_isn(客户端的一个初始序列号);
服务端收到之后返回一个包,报文首部里:SYN标志位为1(同理),ACK为client_isn + 1;整个包的序列号为server_isn(服务端的一个初始序列号);
第三次表示连接已经建立,所以发送的包里面SYN设置为0,ACK为server_isn + 1;整个包的序列号为client_isn + 1;

TCP选项:

每一个SYN可以含有多个TCP选项

1. MSS(Maximum Segment Size)最大分节大小:

接收端表示在本连接中的每个TCP分节中愿意接受的最大数据量,发送端TCP使用接收端的MSS值作为所发送分节的最大大小;
TCP_MAXSEG套接字选项可以提取和设置这个TCP选项;

2. 窗口规模选项:

原来是65535bit,现在由于网速变快接近1G;
在一个TCP连接上使用窗口规模的全体是它的两个端系统必须都支持这个选项。SO_RCVBUF套接字选项可以影响到这个选项

TIME_WAIT状态

执行主动关闭的端经历了这个状态,该断点停留在这个状态的持续时间是最长分节生命期(Maximum Segment Lifetime,MSL)的两倍,2MSL;

MSL是任何IP数据报能够在因特网中存活的最长时间。我们假设具有最大跳限(hop limit)的分组在网络中存在的时间不可能超过MSL。

在此可以查一下重复分组(lost duplicate)的概念

TIME_WAIT状态有两个存在的理由:

1. 可靠的实现TCP全双工连接接的终止

假设4次挥手的最后一个ACK丢失,服务器重新发送一个FIN,这时客户端需要足够的时间再去接收这个FIN并重新发送一个ACK,如果没有TIME_WAIT而是发送完最后一个ACK直接关闭了事,那么如果ACK丢失,那么状态信息则不完整,就不能可靠的实现TCP全双工连接接的终止。

2. 允许老的重复分组在网络中消逝

如果两个地址(IP+端口号)在断开连接之前出现错误,产生了重复分组;还是这两个地址重新连接的时候,有可能老的重复分组传到对端,与新连接里与老的重复分组序列号相同的新分组冲突;为了防止这种情况,断开连接之后,处于TIME_WAIT状态的地址不能建立连接,要等待老的重复分组消逝(TIME_WAIT的时间足够让它消逝)之后才能发起连接。
(一个例外)
如果新连接的SYN的序列号大于前一个连接的结束序列号(可能是最后一个ACK),处于TIME_WAIT的端可以建立连接。

端口号:

采用16位整数的端口号(port number)

well-known端口号:

约定俗成的端口号,如21是FTP
由IANA分配和控制,范围为0~1023

已登记的端口号:

范围1024~49151

临时端口号:

是由传输层协议自动赋予用户,传输层协议代码保证它的唯一性
范围49152~65535

Unix系统有保留端口(reserved port),任何well-known端口号都是保留端口,分配这些端口的服务器应用必须以SU启动。

套接字对(socket pair):

一个TCP连接的套接字对是一个定义该连接的连个断电的四元组:
本机IP地址,本机TCP端口号,外地IP地址,外地TCP端口号

TCP套接字对唯一标识一个网络上的每个TCP连接
标识每个端点的(IP地址和端口号)为套接字(socket)

TCP端口号和并发服务器:

并发服务器中主服务器循环通过派生一个 子进程 来处理新的连接
不同的客户连接到并发服务器的同一个端口的时候,先连接到父进程的监听套接字,然后父进程fork出一个子进程来处理(IP地址和端口号不变,但是不是监听套接字而是已连接套接字)

缓冲区大小及限制:

  • IPv4数据报最大大小为65535Bytes,包括IPv4首部。(因为首部标识总长度的字段为16bit)
  • IPv6数据报最大大小为65575Bytes,包括40Bytes的IPv6首部。(因为首部标识净荷的字段为16bit)
  • 以太网的MTU(Maximum Transmission Unit)为1500Bytes
  • IPv4要求最小链路的MTU为68Bytes,IPv6要求最小链路的MTU为1280Bytes
  • 两个主机之间使用的是路径MTU(为两个主机之间的链路最小MTU)
  • 分片(Fragmentation):大小超过链路的MTU
    IPv4:主机对产生的数据包执行分片,路由器对转发的数据报执行分片
    IPv6:主机对产生的数据包执行分片,路由器对转发的数据报执行分片
  • IPv4首部DF标志位(Don`t Fragment)若被设置,无论主机还是路由器都不执行分片,IPv6隐含一个DF位
    DF位可用作路径MTU发现。
  • 最小重组缓冲区大小(minimum reassembly buffer size), 它是IPv4和
    IPv6的任何实现都必须保证支持的最小数据报大小。IPv4为576Bytes,IPv6为1500Bytes
  • TCP有一个MSS(Maximum Segment Size)最大分节大小,告诉对端每个分节中能够发送的最大TCP的数据量。经常被设置为MTU - IP首部长度 - TCP首部长度;
    以太网:IPv4: 1500-20-20=1460; IPv6: 1500-40-20=1440

TCP输出:

应用进程调用write函数,然后将数据从应用进程缓冲区写入套接字发送缓冲区,如果数据很大,在I/O过程,应用进程投入睡眠;
write函数调用成功产生返回值,表示应用进程缓冲区可以重新使用,不表示对端收到数据;
TCP加上TCP首部之后,构成TCP分节传入数据链路的输出队列,如果输出队列已满,新到的数据将被丢弃,沿协议栈向上返回一个错误,TCP在相应的时刻重传;IP给每一个TCP分节加上IP数据报;
TCP必须为已发送的数据保留一个副本,知道它收到对端发回的确认为止;

UDP输出:

UDP是不可靠的,所以不需要保存已发送数据的副本;
UDP给用户数据加上8Bytes的UDP首部,发送给IP层,然后IP给每个UDP分段加上IP首部放到数据链路层的输出队列;
如果write函数成功返回,说明数据报或者其分段已经被加入输出队列;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值