容易被忽略的网络传输层小知识点

一、端口号的分类以及用途

    众所周知,一个ip地址对应了唯一的主机。而端口号对应了唯一的一台主机的唯一一个网络进程。

    而这两者联系起来就叫套接字。因此套接字对应了唯一的一个网络进程。

    那么,什么是端口号?

    端口号其实就是一个为了标志本计算机应用层中的各个进程在和运输层交互时的层间接口,只具有本地意义。

    因此,两台计算机之间交互,不仅要知道双方的ip地址,也需要知道双方的端口号。可见端口号的重要。

    在TCP/UDP的报头信息中,都含有对应的端口号的字段,其一般为16位。因此其最多可以表示65535个端口。

    那么,这些端口是随意使用吗?答案是:不是的。

    他们是有分类的:

    1、服务器端使用的端口号

        1>、熟知端口号(系统端口号):0~1023(可在网站www.iana.org查阅),一般表示一些比较重要的应用进程。

                常见的有:FTP:21(文件传输协议)

                                  SSH:22(安全登录、文件传送、端口重定向)

                                  TELNET:23(远程终端协议)

                                  SMPT:25(简单E-mail传送协议)

                                  DNS:53(域名系统)

                                  TFTP:69(简单文本传送协议)

                                  HTTP:80(超文本传送协议)

                                  SNMP:161(简单网络管理协议)

                                  HTTPS:443(加密的HTTP)

        2>、登记端口号:1024~49151,是为没有熟知端口号的应用进程使用的。使用前必须先登记,以防止重复。

    2、客户端使用的端口号

        49152~65535,这类端口号是留给客户进程选择暂时使用的。使用完后,还可以供其他进程使用。


二、TCP报头信息中的URG字段和PSH字段

    在TCP报头信息中,有6个只占了一位的字段(URG/ACK/PSH/RET/SYN/FIN),这两个就包含在内。

    1、URG(URGent)

        又叫紧急URG,TCP报头中有一个16位紧急指针字段。当URG字段为1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应该尽快传送(相当于优先级高的数据),而不是按照原来的排队顺序来传送。

        比如,用户需要Ctrl+C来发送中断命令。那么应该立刻处理该中断,因此需要将该数据做紧急处理。那么,如何处理呢?

        发送方TCP就吧紧急数据直接插入在本报文段数据的最前边。

    2、PSH(PuSH)

        又叫推送PSH,当两个应用进程在进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后就能够立即收到对方的响应。在这种情况下,就可以将PSH字段置为1,并立即创建一个报文段发出去。

    接收方收到后,就尽快的交付接受应用进程,而不再等待缓冲区满了在交付。(一般很少使用)

    两者看似相似,都是处理优先级比较高的数据。但两者最大的区别就是上边粗体部分的区别。


三、常见的TCP四种计时器

    众所周知,TCP是一个安全可靠的传输层协议。那么,要做到这一点,就势必会比较复杂。那么,TCP是如何保证这一点呢?

    首先,TCP是一个面向连接的,全双工的,面向字节流的传输协议。

    既然面向连接,因此就需要通信双方共同来维护一个数据结构(哪一种数据结构,这里不做讨论)。还有它的停止等待协议(请求/响应),滑动窗口,流量控制,拥塞控制,超时重传等机制来共同维护。

    那么,下边是4种常见的用来维护TCP可靠信的计时器

    1、超时重传计时器(属于停止等待协议范畴)

       

    如上图所示,如果在发送数据过程中,数据丢失。如果没有这个定时器,那么这个数据将会被永远丢失。因此,为了保证数据不被丢失,设定一个超时计时器(时间要大于数据平均往返时间)(其实往返时间是不定的,这和当时场景下的网络时延有关。这样,只是为了更加简单的讲解这个问题)。在发送数据时,暂时保留已发送的数据的副本,启动计时器,在计时器结束前,还没有收到确认消息。那么就认为数据丢失,进行重传。

    当然,还有两种情况就是确认丢失和确认迟到。这里不做讲解。


     2、持续计时器(属于流量控制范畴)

    所谓流量控制,其实就是让发送发发的慢一点,使得接收方来得及接受。

    因此,使用了滑动窗口的机制实现了流量控制。

    考虑如下场景:

    我们很清楚,在网络传输中,任何一条消息都有可能丢失。不管是发送消息,还是确认消息等等。假如接收方的窗口大小为1024。并且此时,接收方的窗口已经没有剩余。那么接收方就会给发送方发送一条零窗口通知(告诉发送方,不要再发了,我的窗口大小已经是0)。此时,发送方将不再发送数据。过了一会,接受方的一部分数据交付给了上层,窗口又有了一定的空间,此时接收方就会给发送方发送一条非零窗口通知。但是,不幸的是,这条消息丢失了。那么这样,接收方一直等发送方的确认,而发送方一直等接收方发非零窗口通知。这样,就进入了死锁的局面。

    因此,为了解决这个问题,TCP为每一个连接设有一个持续计时器。只要TCP连接的一方收到对方的零窗口通知,就自动计时。如果时间已到,就发送一个零窗口探测报文(仅仅携带一个字节的数据),而对方就会在确认这个探测报文段时给出现在的窗口大小。如果仍为0,就重新设置计时器。这样就不会死锁。


    3、等待计时器(属于连接释放范畴)

    在释放连接后,主动发起释放的一方需要等待2MSL(最长报文段寿命)。这是为什么?

    (假设客户端发起释放连接)

    1>、为了保证客户端发送的最后一条确认消息能够准确到达服务器。如果该消息丢失,那么服务器就会启动超时重传机制,在客户端收到该超时重传的消息后,重新设定该计时器的时间为2MSL,然后再可以发送一个确认消息。否则,如果没有这个计时器,再最后一条确认消息丢失后,客户端已经关闭。而服务器永远不会收到那条确认消息,也因此永远不能释放连接。

    2>、防止“已失效的连接请求报文段”。客户端在发送完最后一个ACK报文段后,再经过2MSL时间,就可以使本连接持续的时间内所产生的所有报文段从网络中消失。这样就不会下一个新的连接中出现旧的连接请求报文段。


    4、保活计时器(属于连接与释放连接范畴)

    考虑这样一个场景:客户已主动与服务器建立了TCP连接。但后来客户端主机突然故障。显然,服务器以后就不能收到该 客户机的消息,那怎么办?

    使用该计时器,服务器没收到一次客户的请求,就重新设置该计时器,通常为2小时。如果2个小时内没有收到客户的数据,服务器就发送一个探测报文段,以后则每隔75分钟发送一次。如果发送10个探测报文段后仍无客户的响应,服务器就认为客户端出了故障,接着就关闭连接。