tcp 订阅
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793 [1]  定义。TCP旨在适应支持多网络应用的分层协议层次结构。 连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。TCP假设它可以从较低级别的协议获得简单的,可能不可靠的数据报服务。 原则上,TCP应该能够在从硬线连接到分组交换或电路交换网络的各种通信系统之上操作。 展开全文
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793 [1]  定义。TCP旨在适应支持多网络应用的分层协议层次结构。 连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。TCP假设它可以从较低级别的协议获得简单的,可能不可靠的数据报服务。 原则上,TCP应该能够在从硬线连接到分组交换或电路交换网络的各种通信系统之上操作。
信息
工    作
与IP协议共同使用
外文名
Transmission Control Protocol
数据格式
字节流
中文名
传输控制协议
应用层次
传输层
服    务
由套接字端点获得
TCP简介
传输控制协议(TCP,Transmission Control Protocol)是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。 [2]  互联网络与单个网络有很大的不同,因为互联网络的不同部分可能有截然不同的拓扑结构、带宽、延迟、数据包大小和其他参数。TCP的设计目标是能够动态地适应互联网络的这些特性,而且具备面对各种故障时的健壮性。 [2]  不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。 [3]  应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元(MTU)的限制)。之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。 [3]  每台支持TCP的机器都有一个TCP传输实体。TCP实体可以是一个库过程、一个用户进程,或者内核的一部分。在所有这些情形下,它管理TCP流,以及与IP层之间的接口。TCP传输实体接受本地进程的用户数据流,将它们分割成不超过64KB(实际上去掉IP和TCP头,通常不超过1460数据字节)的分段,每个分段以单独的IP数据报形式发送。当包含TCP数据的数据报到达一台机器时,它们被递交给TCP传输实体,TCP传输实体重构出原始的字节流。为简化起见,我们有时候仅仅用“TCP”来代表TCP传输实体(一段软件)或者TCP协议(一组规则)。根据上下文语义你应该能很消楚地推断出其实际含义。例如,在“用户将数据交给TCP”这句话中,很显然这里指的是TCP传输实体。 [2]  IP层并不保证数据报一定被正确地递交到接收方,也不指示数据报的发送速度有多快。正是TCP负责既要足够快地发送数据报,以便使用网络容量,但又不能引起网络拥塞:而且,TCP超时后,要重传没有递交的数据报。即使被正确递交的数据报,也可能存在错序的问题,这也是TCP的责任,它必须把接收到的数据报重新装配成正确的顺序。简而言之,TCP必须提供可靠性的良好性能,这正是大多数用户所期望的而IP又没有提供的功能。 [2] 
收起全文
精华内容
下载资源
问答
  • TCP和UDP的最完整的区别

    万次阅读 多人点赞 2016-08-04 11:30:30
    TCP和UDP两种协议的比较汇总

    欢迎访问个人网站:码到城攻

    TCP UDP
    TCP与UDP基本区别
      1.基于连接与无连接
      2.TCP要求系统资源较多,UDP较少; 
      3.UDP程序结构较简单 
      4.流模式(TCP)与数据报模式(UDP); 
      5.TCP保证数据正确性,UDP可能丢包 

      6.TCP保证数据顺序,UDP不保证 
      
    UDP应用场景:
      1.面向数据报方式
      2.网络数据大多为短消息 
      3.拥有大量Client
      4.对数据安全性无特殊要求

      5.网络负担非常重,但对响应速度要求高
     
    具体编程时的区别
       1.socket()的参数不同 
       2.UDP Server不需要调用listen和accept 
       3.UDP收发数据用sendto/recvfrom函数 
       4.TCP:地址信息在connect/accept时确定 
       5.UDP:在sendto/recvfrom函数中每次均 需指定地址信息 
       6.UDP:shutdown函数无效

     
    编程区别
       通常我们在说到网络编程时默认是指TCP编程,即用前面提到的socket函数创建一个socket用于TCP通讯,函数参数我们通常填为SOCK_STREAM。即socket(PF_INET, SOCK_STREAM, 0),这表示建立一个socket用于流式网络通讯。 
       SOCK_STREAM这种的特点是面向连接的,即每次收发数据之前必须通过connect建立连接,也是双向的,即任何一方都可以收发数据,协议本身提供了一些保障机制保证它是可靠的、有序的,即每个包按照发送的顺序到达接收方。 

      而SOCK_DGRAM这种是User Datagram Protocol协议的网络通讯,它是无连接的,不可靠的,因为通讯双方发送数据后不知道对方是否已经收到数据,是否正常收到数据。任何一方建立一个socket以后就可以用sendto发送数据,也可以用recvfrom接收数据。根本不关心对方是否存在,是否发送了数据。它的特点是通讯速度比较快。大家都知道TCP是要经过三次握手的,而UDP没有。 


    基于上述不同,UDP和TCP编程步骤也有些不同,如下:

    TCP: 
    TCP编程的服务器端一般步骤是: 
      1、创建一个socket,用函数socket(); 
      2、设置socket属性,用函数setsockopt(); * 可选 
      3、绑定IP地址、端口等信息到socket上,用函数bind(); 
      4、开启监听,用函数listen(); 
      5、接收客户端上来的连接,用函数accept(); 
      6、收发数据,用函数send()和recv(),或者read()和write(); 
      7、关闭网络连接; 
      8、关闭监听; 

    TCP编程的客户端一般步骤是: 
      1、创建一个socket,用函数socket(); 
      2、设置socket属性,用函数setsockopt();* 可选 
      3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 
      4、设置要连接的对方的IP地址和端口等属性; 
      5、连接服务器,用函数connect(); 
      6、收发数据,用函数send()和recv(),或者read()和write(); 
      7、关闭网络连接;

    UDP:
    与之对应的UDP编程步骤要简单许多,分别如下: 
      UDP编程的服务器端一般步骤是: 
      1、创建一个socket,用函数socket(); 
      2、设置socket属性,用函数setsockopt();* 可选 
      3、绑定IP地址、端口等信息到socket上,用函数bind(); 
      4、循环接收数据,用函数recvfrom(); 
      5、关闭网络连接; 

    UDP编程的客户端一般步骤是: 
      1、创建一个socket,用函数socket(); 
      2、设置socket属性,用函数setsockopt();* 可选 
      3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 
      4、设置对方的IP地址和端口等属性; 
      5、发送数据,用函数sendto(); 
      6、关闭网络连接;

    TCP和UDP是OSI模型中的运输层中的协议。TCP提供可靠的通信传输,而UDP则常被用于让广播和细节控制交给应用的通信传输。

    UDP补充:
       UDP不提供复杂的控制机制,利用IP提供面向无连接的通信服务。并且它是将应用程序发来的数据在收到的那一刻,立刻按照原样发送到网络上的一种机制。即使是出现网络拥堵的情况下,UDP也无法进行流量控制等避免网络拥塞的行为。此外,传输途中如果出现了丢包,UDO也不负责重发。甚至当出现包的到达顺序乱掉时也没有纠正的功能。如果需要这些细节控制,那么不得不交给由采用UDO的应用程序去处理。换句话说,UDP将部分控制转移到应用程序去处理,自己却只提供作为传输层协议的最基本功能。UDP有点类似于用户说什么听什么的机制,但是需要用户充分考虑好上层协议类型并制作相应的应用程序。

    TCP补充:
      TCP充分实现了数据传输时各种控制功能,可以进行丢包的重发控制,还可以对次序乱掉的分包进行顺序控制。而这些在UDP中都没有。此外,TCP作为一种面向有连接的协议,只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费。TCP通过检验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现可靠性传输。


    TCP与UDP区别总结:
    1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
    2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保   证可靠交付
    3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
      UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
    4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
    5、TCP首部开销20字节;UDP的首部开销小,只有8个字节
    6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

    展开全文
  • TCP/IP协议详解

    万次阅读 多人点赞 2019-05-11 08:40:41
    认识HTTP协议 它是互联网协议(Internet Protocol Suite),一个网络通信模型,是互联网的一个基本的构架。 HTTP协议是Hyper Text Transfer ... HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件...

    为什么会有TCP/IP协议

    在世界上各地,各种各样的电脑运行着各自不同的操作系统为大家服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别。就好像圣经中上帝打乱了各地人的口音,让他们无法合作一样。计算机使用者意识到,计算机只是单兵作战并不会发挥太大的作用。只有把它们联合起来,电脑才会发挥出它最大的潜力。于是人们就想方设法的用电线把电脑连接到了一起。

    但是简单的连到一起是远远不够的,就好像语言不同的两个人互相见了面,完全不能交流信息。因而他们需要定义一些共通的东西来进行交流,TCP/IP就是为此而生。TCP/IP不是一个协议,而是一个协议族的统称。里面包括了IP协议,IMCP协议,TCP协议,以及我们更加熟悉的http、ftp、pop3协议等等。电脑有了这些,就好像学会了外语一样,就可以和其他的计算机终端做自由的交流了。

    TCP/IP模型

    在这里插入图片描述
    应用层:
    向用户提供一组常用的应用程序,比如电子邮件、文件传输访问、远程登录等。远程登录TELNET使用TELNET协议提供在网络其它主机上注册的接口。TELNET会话提供了基于字符的虚拟终端。文件传输访问FTP使用FTP协议来提供网络内机器间的文件拷贝功能。

    传输层:
    提供应用程序间的通信。其功能包括:一、格式化信息流;二、提供可靠传输。为实现后者,传输层协议规定接收端必须发回确认,并且假如分组丢失,必须重新发送。

    网络层 :
    负责相邻计算机之间的通信。其功能包括三方面。
    一、处理来自传输层的分组发送请求,收到请求后,将分组装入IP数据报,填充报头,选择去往信宿机的路径,然后将数据报发往适当的网络接口。

    二、处理输入数据报:首先检查其合法性,然后进行寻径–假如该数据报已到达信宿机,则去掉报头,将剩下部分交给适当的传输协议;假如该数据报尚未到达信宿,则转发该数据报。

    三、处理路径、流控、拥塞等问题。

    网络接口层:
    这是TCP/IP软件的最低层,负责接收IP数据报并通过网络发送之,或者从网络上接收物理帧,抽出IP数据报,交给IP层。

    IP

    IP 用于计算机之间的通信。

    IP 是无连接的通信协议。它不会占用两个正在通信的计算机之间的通信线路。这样,IP 就降低了对网络线路的需求。每条线可以同时满足许多不同的计算机之间的通信需要。

    通过 IP,消息(或者其他数据)被分割为小的独立的包,并通过因特网在计算机之间传送。

    IP 负责将每个包路由至它的目的地。

    IP地址

    每个计算机必须有一个 IP 地址才能够连入因特网。

    每个 IP 包必须有一个地址才能够发送到另一台计算机。

    网络上每一个节点都必须有一个独立的Internet地址(也叫做IP地址)。现在,通常使用的IP地址是一个32bit的数字,也就是我们常说的IPv4标准,这32bit的数字分成四组,也就是常见的255.255.255.255的样式。IPv4标准上,地址被分为五类,我们常用的是B类地址。具体的分类请参考其他文档。需要注意的是IP地址是网络号+主机号的组合,这非常重要。

    CP/IP 使用 32 个比特来编址。一个计算机字节是 8 比特。所以 TCP/IP 使用了 4 个字节。
    一个计算机字节可以包含 256 个不同的值:
    00000000、00000001、00000010、00000011、00000100、00000101、00000110、00000111、00001000 … 直到 11111111。
    现在,你知道了为什么 TCP/IP 地址是介于 0 到 255 之间的 4 个数字。

    TCP 使用固定的连接

    TCP 用于应用程序之间的通信。

    当应用程序希望通过 TCP 与另一个应用程序通信时,它会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP 将在两个应用程序之间建立一个全双工 (full-duplex) 的通信。

    这个全双工的通信将占用两个计算机之间的通信线路,直到它被一方或双方关闭为止。

    UDP 和 TCP 很相似,但是更简单,同时可靠性低于 TCP。

    IP 路由器

    当一个 IP 包从一台计算机被发送,它会到达一个 IP 路由器。

    IP 路由器负责将这个包路由至它的目的地,直接地或者通过其他的路由器。

    在一个相同的通信中,一个包所经由的路径可能会和其他的包不同。而路由器负责根据通信量、网络中的错误或者其他参数来进行正确地寻址。

    域名

    12 个阿拉伯数字很难记忆。使用一个名称更容易。

    用于 TCP/IP 地址的名字被称为域名。www.baidu.com就是一个域名。

    当你键入一个像https://www.baidu.com/这样的域名,域名会被一种 DNS 程序翻译为数字。

    在全世界,数量庞大的 DNS 服务器被连入因特网。DNS 服务器负责将域名翻译为 TCP/IP 地址,同时负责使用新的域名信息更新彼此的系统。

    当一个新的域名连同其 TCP/IP 地址一同注册后,全世界的 DNS 服务器都会对此信息进行更新。

    TCP/IP

    TCP/IP 意味着 TCP 和 IP 在一起协同工作。

    TCP 负责应用软件(比如你的浏览器)和网络软件之间的通信。

    IP 负责计算机之间的通信。

    TCP 负责将数据分割并装入 IP 包,然后在它们到达的时候重新组合它们。

    IP 负责将包发送至接受者。

    TCP报文格式

    在这里插入图片描述
    16位源端口号:16位的源端口中包含初始化通信的端口。源端口和源IP地址的作用是标识报文的返回地址。

    16位目的端口号:16位的目的端口域定义传输的目的。这个端口指明报文接收计算机上的应用程序地址接口。

    32位序号:32位的序列号由接收端计算机使用,重新分段的报文成最初形式。当SYN出现,序列码实际上是初始序列码(Initial Sequence Number,ISN),而第一个数据字节是ISN+1。这个序列号(序列码)可用来补偿传输中的不一致。

    32位确认序号:32位的序列号由接收端计算机使用,重组分段的报文成最初形式。如果设置了ACK控制位,这个值表示一个准备接收的包的序列码。

    4位首部长度:4位包括TCP头大小,指示何处数据开始。

    保留(6位):6位值域,这些位必须是0。为了将来定义新的用途而保留。

    标志:6位标志域。表示为:紧急标志、有意义的应答标志、推、重置连接标志、同步序列号标志、完成发送数据标志。按照顺序排列是:URG、ACK、PSH、RST、SYN、FIN。

    16位窗口大小:用来表示想收到的每个TCP数据段的大小。TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个16字节字段,因而窗口大小最大为65535字节。

    16位校验和:16位TCP头。源机器基于数据内容计算一个数值,收信息机要与源机器数值 结果完全一样,从而证明数据的有效性。检验和覆盖了整个的TCP报文段:这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证的。

    16位紧急指针:指向后面是优先数据的字节,在URG标志设置了时才有效。如果URG标志没有被设置,紧急域作为填充。加快处理标示为紧急的数据段。

    选项:长度不定,但长度必须为1个字节。如果没有选项就表示这个1字节的域等于0。

    数据:该TCP协议包负载的数据。

    在上述字段中,6位标志域的各个选项功能如下。

    URG:紧急标志。紧急标志为"1"表明该位有效。

    ACK:确认标志。表明确认编号栏有效。大多数情况下该标志位是置位的。TCP报头内的确认编号栏内包含的确认编号(w+1)为下一个预期的序列编号,同时提示远端系统已经成功接收所有数据。

    PSH:推标志。该标志置位时,接收端不将该数据进行队列处理,而是尽可能快地将数据转由应用处理。在处理Telnet或rlogin等交互模式的连接时,该标志总是置位的。

    RST:复位标志。用于复位相应的TCP连接。

    SYN:同步标志。表明同步序列编号栏有效。该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号,该序列编号为TCP连接初始端(一般是客户端)的初始序列编号。在这里,可以把TCP序列编号看作是一个范围从0到4,294,967,295的32位计数器。通过TCP连接交换的数据中每一个字节都经过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号。

    FIN:结束标志。

    TCP三次握手

    所谓三次握手(Three-Way Handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。在socket编程中,这一过程由客户端执行connect来触发,整个流程如下图所示:
    在这里插入图片描述
    (1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。

    (2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。

    (3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。

    简单来说,就是

    1、建立连接时,客户端发送SYN包(SYN=i)到服务器,并进入到SYN-SEND状态,等待服务器确认

    2、服务器收到SYN包,必须确认客户的SYN(ack=i+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器进入SYN-RECV状态

    3、客户端收到服务器的SYN+ACK包,向服务器发送确认报ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手,客户端与服务器开始传送数据。

    SYN攻击:

    在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将产时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。SYN攻击时一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了,使用如下命令可以让之现行:

    #netstat -nap | grep SYN_RECV
    

    TCP四次挥手

    所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发,整个流程如下图所示:
    在这里插入图片描述
    由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。

    (1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。

    (2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。

    (3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。

    (4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。

    为什么建立连接是三次握手,而关闭连接却是四次挥手呢?

    这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。

    为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
    原因有二:
    一、保证TCP协议的全双工连接能够可靠关闭
    二、保证这次连接的重复数据段从网络中消失

    先说第一点,如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACK,Server就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。所以,Client不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。

    再说第二点,如果Client直接CLOSED,然后又再向Server发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依据是socket pair,于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。

    认识HTTP协议

    它是互联网协议(Internet Protocol Suite),一个网络通信模型,是互联网的一个基本的构架。

    HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。

    HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。

    HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中,而且HTTP-NG(Next Generation of HTTP)的建议已经提出。

    HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。

    TCP/IP协议它们并不是一个协议,而是一个协议簇,这些协议的目的,就是使计算机之间可以进行信息交换,并且两大协议其中都包含其他的协议,虽然放在了一起,但它们的作用和工作是不一样的。

    HTTP协议定义了内容的格式,这是一个应用层的协议,应用层协议的内容需要通过传输层在浏览器和服务器之间传送,TCP/IP协议是ISO网络参考模型的一种实现。在TCP/IP协议中,与网络程序员相关的主要有两层:传输层和应用层。

    传输层协议负责解决数据传输问题,包括数据通行的可靠性问题。传输层依赖更底层的网络层来完成实际的数据传输,在TCP/IP网络协议中,负责可靠通信的传输层协议为TCP协议。而网络层一般用网络驱动来实现,普通的程序员不会涉及;在TCP/IP协议中,网络层的协议为IP协议。

    HTTP请求处理图解

    浏览器与Web服务器之间的协议是应用层协议,当前,我们主要遵循的协议为HTTP/1.1。HTTP协议是Web开发的基础,这是一个无状态的协议,客户机与服务器之间通过请求和相应完成一次会话(Session)。
    在这里插入图片描述

    客户端、web服务器、HTTP三者之间的联系

    (1)客户端与web服务器工作过程
    当浏览器寻找到Web服务器的地址之后,浏览器帮助我们把对服务器的请求转换为一系列参数发送给Web服务器。服务器受到浏览器发来的请求参数之后,将会分析这些数据,并进行处理。然后向浏览器回应处理的结果,也就是一些新的数据;这些数据通常是HTML网页或者图片。浏览器收到之后,解析这些数据,将它们呈现在浏览器的窗口中,这就是我们看到的网页。
    (2)客户端与web服务器遵守共同标准:HTTP协议
    在浏览器与Web服务器的对话中,需要使用双方都能够理解的语法规范进行通信,这种程序之间进行通信的语法规范,我们称之为协议。协议有许多种,根据国际标准化组织ISO的网络参考模型,程序与程序之间的通信可分为7层,从低到高依次为:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

    ISO模型:
    在这里插入图片描述
    (3)客户端、web服务器、数据库服务器图解
    在这里插入图片描述

    浏览器与服务器图解

    HTTP协议就是TCP/IP协议中专门用于浏览器与Web服务器之间通信的应用层协议。应用层协议依赖于传输层协议完成数据传输,传输层协议依赖于网络层协议王城数据传输,他们之间的关系如下图(浏览器与服务器之间网络通信的传输过程):
    在这里插入图片描述

    写在后面

    如果觉得本文帮助了你,还请高抬贵手赠予 uh5 项目 一个 Star。

    展开全文
  • TCP 详解

    万次阅读 多人点赞 2018-06-20 00:30:36
    上回说到 UDP 协议, 与之对应的便是 TCP 协议 TCP协议 TCP协议全称: 传输控制协议, 顾名思义, 就是要对数据的传输进行一定的控制. 先来看看它的报头 我们来分析分析每部分的含义和作用 源端口号/目的端口号:...

    上回说到 UDP 协议, 与之对应的便是 TCP 协议

    TCP协议

    TCP协议全称: 传输控制协议, 顾名思义, 就是要对数据的传输进行一定的控制.
    先来看看它的报头
    Alt text

    我们来分析分析每部分的含义和作用

    • 源端口号/目的端口号: 表示数据从哪个进程来, 到哪个进程去.
    • 32位序号:
    • 4位首部长度: 表示该tcp报头有多少个4字节(32个bit)
    • 6位保留: 顾名思义, 先保留着, 以防万一
    • 6位标志位

      URG: 标识紧急指针是否有效
      ACK: 标识确认序号是否有效
      PSH: 用来提示接收端应用程序立刻将数据从tcp缓冲区读走
      RST: 要求重新建立连接. 我们把含有RST标识的报文称为复位报文段
      SYN: 请求建立连接. 我们把含有SYN标识的报文称为同步报文段
      FIN: 通知对端, 本端即将关闭. 我们把含有FIN标识的报文称为结束报文段

    • 16位窗口大小:

    • 16位检验和: 由发送端填充, 检验形式有CRC校验等. 如果接收端校验不通过, 则认为数据有问题. 此处的校验和不光包含TCP首部, 也包含TCP数据部分.
    • 16位紧急指针: 用来标识哪部分数据是紧急数据.
    • 选项和数据暂时忽略

    连接管理机制

    正常情况下, tcp需要经过三次握手建立连接, 四次挥手断开连接.

    那么什么是三次握手? 什么是四次挥手呢?

    三次握手

    第一次:
    客户端 - - > 服务器 此时服务器知道了客户端要建立连接了
    第二次:
    客户端 < - - 服务器 此时客户端知道服务器收到连接请求了
    第三次:
    客户端 - - > 服务器 此时服务器知道客户端收到了自己的回应

    到这里, 就可以认为客户端与服务器已经建立了连接.

    再来看个图.
    Alt text

    刚开始, 客户端和服务器都处于 CLOSE 状态.
    此时, 客户端向服务器主动发出连接请求, 服务器被动接受连接请求.

    1, TCP服务器进程先创建传输控制块TCB, 时刻准备接受客户端进程的连接请求, 此时服务器就进入了 LISTEN(监听)状态
    2, TCP客户端进程也是先创建传输控制块TCB, 然后向服务器发出连接请求报文,此时报文首部中的同步标志位SYN=1, 同时选择一个初始序列号 seq = x, 此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定, SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
    3, TCP服务器收到请求报文后, 如果同意连接, 则发出确认报文。确认报文中的 ACK=1, SYN=1, 确认序号是 x+1, 同时也要为自己初始化一个序列号 seq = y, 此时, TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据, 但是同样要消耗一个序号。
    4, TCP客户端进程收到确认后还, 要向服务器给出确认。确认报文的ACK=1,确认序号是 y+1,自己的序列号是 x+1.
    5, 此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。

    为什么不用两次?

    • 主要是为了防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送的第一个请求连接并且没有丢失,只是因为在网络中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时之前滞留的那一次请求连接,因为网络通畅了, 到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的费。
      如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

    为什么不用四次?

    • 因为三次已经可以满足需要了, 四次就多余了.

    再来看看何为四次挥手.

    数据传输完毕后,双方都可以释放连接.
    此时客户端和服务器都是处于ESTABLISHED状态,然后客户端主动断开连接,服务器被动断开连接.

    1, 客户端进程发出连接释放报文,并且停止发送数据。
    释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
    2, 服务器收到连接释放报文,发出确认报文,ACK=1,确认序号为 u+1,并且带上自己的序列号seq=v,此时服务端就进入了CLOSE-WAIT(关闭等待)状态。
    TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
    3, 客户端收到服务器的确认请求后,此时客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最终数据)
    4, 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,确认序号为v+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
    5, 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,确认序号为w+1,而自己的序列号是u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
    6, 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

    再来看一张图.
    Alt text

    为什么最后客户端还要等待 2*MSL的时间呢?

    • MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值。

    • 第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。

    • 第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。

    为什么建立连接是三次握手,关闭连接确是四次挥手呢?

    • 建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
      而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。

    如果已经建立了连接, 但是客户端突发故障了怎么办?

    • TCP设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75分钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

    理解TIME_WAIT状态

    可以做一个实验, 先运行server, 再运行client连接server, 然后断开server, 再立马运行server.
    我们会发现:
    这里写图片描述

    绑定的时候出了问题.
    这是因为,虽然server应用程序终止了,但TCP协议层的连接并没有完全断开,因此不能再次监听绑定同样的server端口.

    TCP协议规定,主动关闭连接的一方要处于TIME_ WAIT状态,等待2*MSL(maximum segment lifetime)的时间后才能回到CLOSED状态.
    我们使用Ctrl-C终止了server, 所以server是主动关闭连接的一方, 在TIME_WAIT期间仍然不能再次监听同样的server端口
    MSL在RFC1122中规定为两分钟,但是各操作系统的实现不同, 在Centos7上默认配置的值是60s;
    可以通过 cat /proc/sys/net/ipv4/tcp_fin_timeout 查看MSL的值
    这里写图片描述
    解决TIME_WAIT引起的bind失败问题
    在server的TCP连接没有完全断开之前不允许重新监听, 某些情况下可能是不合理的.

    比如:

    服务器需要处理非常大量的客户端的连接(每个连接的生存时间可能很短, 但是每秒都有大量的客户端来请求).
    这个时候如果由服务器端主动关闭连接(比如某些客户端不活跃, 就需要被服务器端主动清理掉), 就会产生大量TIME_WAIT连接.
    由于我们的请求量很大, 就可能导致TIME_WAIT的连接数很多, 导致服务器的端口不够用, 无法处理新的连接.

    解决方法:
    - 使用setsockopt()设置socket描述符的选项SO_REUSEADDR为1, 表示允许创建端口号相同但IP地址不同的多个socket描述符.

    用法:

    • 在server代码的socket()和bind()调用之间插入如下代码

      int opt = 1;
      setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    确认应答机制(ACK机制)

    这里写图片描述

    TCP将每个字节的数据都进行了编号, 即为序列号.
    这里写图片描述

    每一个ACK都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据; 下一次你要从哪里开始发.
    比如, 客户端向服务器发送了1005字节的数据, 服务器返回给客户端的确认序号是1003, 那么说明服务器只收到了1-1002的数据.
    1003, 1004, 1005都没收到.
    此时客户端就会从1003开始重发.

    超时重传机制

    这里写图片描述

    主机A发送数据给B之后, 可能因为网络拥堵等原因, 数据无法到达主机B
    如果主机A在一个特定时间间隔内没有收到B发来的确认应答, 就会进行重发
    但是主机A没收到确认应答也可能是ACK丢失了.
    这里写图片描述

    这种情况下, 主机B会收到很多重复数据.
    那么TCP协议需要识别出哪些包是重复的, 并且把重复的丢弃.
    这时候利用前面提到的序列号, 就可以很容易做到去重.

    超时时间如何确定?
    最理想的情况下, 找到一个最小的时间, 保证 “确认应答一定能在这个时间内返回”.
    但是这个时间的长短, 随着网络环境的不同, 是有差异的.
    如果超时时间设的太长, 会影响整体的重传效率; 如果超时时间设的太短, 有可能会频繁发送重复的包.

    TCP为了保证任何环境下都能保持较高性能的通信, 因此会动态计算这个最大超时时间.

    • Linux中(BSD Unix和Windows也是如此), 超时以500ms为一个单位进行控制, 每次判定超时重发的超时时间都是500ms的整数倍.
      如果重发一次之后, 仍然得不到应答, 等待 2*500ms 后再进行重传. 如果仍然得不到应答, 等待 4*500ms 进行重传.
      依次类推, 以指数形式递增. 累计到一定的重传次数, TCP认为网络异常或者对端主机出现异常, 强制关闭连接.

    滑动窗口

    刚才我们讨论了确认应答机制, 对每一个发送的数据段, 都要给一个ACK确认应答. 收到ACK后再发送下一个数据段.
    这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返时间较长的时候.
    那么我们可不可以一次发送多个数据段呢?
    例如这样:
    这里写图片描述
    一个概念: 窗口
    窗口大小指的是无需等待确认应答就可以继续发送数据的最大值.
    上图的窗口大小就是4000个字节 (四个段).

    发送前四个段的时候, 不需要等待任何ACK, 直接发送
    收到第一个ACK确认应答后, 窗口向后移动, 继续发送第五六七八段的数据…

    因为这个窗口不断向后滑动, 所以叫做滑动窗口.
    操作系统内核为了维护这个滑动窗口, 需要开辟发送缓冲区来记录当前还有哪些数据没有应答
    只有ACK确认应答过的数据, 才能从缓冲区删掉.
    这里写图片描述

    如果出现了丢包, 那么该如何进行重传呢?

    此时分两种情况讨论:

    1, 数据包已经收到, 但确认应答ACK丢了.
    这里写图片描述
    这种情况下, 部分ACK丢失并无大碍, 因为还可以通过后续的ACK来确认对方已经收到了哪些数据包.

    2, 数据包丢失
    这里写图片描述

    当某一段报文丢失之后, 发送端会一直收到 1001 这样的ACK, 就像是在提醒发送端 “我想要的是 1001”
    如果发送端主机连续三次收到了同样一个 “1001” 这样的应答, 就会将对应的数据 1001 - 2000 重新发送
    这个时候接收端收到了 1001 之后, 再次返回的ACK就是7001了
    因为2001 - 7000接收端其实之前就已经收到了, 被放到了接收端操作系统内核的接收缓冲区中.

    这种机制被称为 “高速重发控制” ( 也叫 “快重传” )

    流量控制

    接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被填满, 这个时候如果发送端继续发送, 就会造成丢包, 进而引起丢包重传等一系列连锁反应.
    因此TCP支持根据接收端的处理能力, 来决定发送端的发送速度.
    这个机制就叫做 流量控制(Flow Control)

    接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 “窗口大小” 字段,
    通过ACK通知发送端;
    窗口大小越大, 说明网络的吞吐量越高;
    接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端;
    发送端接受到这个窗口大小的通知之后, 就会减慢自己的发送速度;
    如果接收端缓冲区满了, 就会将窗口置为0;
    这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 让接收端把窗口大小再告诉发送端.

    这里写图片描述

    那么接收端如何把窗口大小告诉发送端呢?
    我们的TCP首部中, 有一个16位窗口大小字段, 就存放了窗口大小的信息;
    16位数字最大表示65536, 那么TCP窗口最大就是65536字节么?
    实际上, TCP首部40字节选项中还包含了一个窗口扩大因子M, 实际窗口大小是窗口字段的值左移 M 位(左移一位相当于乘以2).

    拥塞控制

    虽然TCP有了滑动窗口这个大杀器, 能够高效可靠地发送大量数据.
    但是如果在刚开始就发送大量的数据, 仍然可能引发一些问题.
    因为网络上有很多计算机, 可能当前的网络状态已经比较拥堵.
    在不清楚当前网络状态的情况下, 贸然发送大量数据, 很有可能雪上加霜.

    因此, TCP引入 慢启动 机制, 先发少量的数据, 探探路, 摸清当前的网络拥堵状态以后, 再决定按照多大的速度传输数据.

    这里写图片描述

    在此引入一个概念 拥塞窗口

    • 发送开始的时候, 定义拥塞窗口大小为1;
    • 每次收到一个ACK应答, 拥塞窗口加1;
    • 每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口

    像上面这样的拥塞窗口增长速度, 是指数级别的.
    “慢启动” 只是指初使时慢, 但是增长速度非常快.
    为了不增长得那么快, 此处引入一个名词叫做慢启动的阈值, 当拥塞窗口的大小超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长.

    这里写图片描述

    • 当TCP开始启动的时候, 慢启动阈值等于窗口最大值
    • 在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回1

    少量的丢包, 我们仅仅是触发超时重传;
    大量的丢包, 我们就认为是网络拥塞;
    当TCP通信开始后, 网络吞吐量会逐渐上升;
    随着网络发生拥堵, 吞吐量会立刻下降.

    拥塞控制, 归根结底是TCP协议想尽可能快的把数据传输给对方, 但是又要避免给网络造成太大压力的折中方案.

    延迟应答

    如果接收数据的主机立刻返回ACK应答, 这时候返回的窗口可能比较小.
    假设接收端缓冲区为1M. 一次收到了500K的数据;
    如果立刻应答, 返回的窗口大小就是500K;
    但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了; 在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来;
    如果接收端稍微等一会儿再应答, 比如等待200ms再应答, 那么这个时候返回的窗口大小就是1M

    窗口越大, 网络吞吐量就越大, 传输效率就越高.
    TCP的目标是在保证网络不拥堵的情况下尽量提高传输效率;

    那么所有的数据包都可以延迟应答么?
    肯定也不是
    有两个限制

    • 数量限制: 每隔N个包就应答一次
    • 时间限制: 超过最大延迟时间就应答一次

    具体的数量N和最大延迟时间, 依操作系统不同也有差异
    一般 N 取2, 最大延迟时间取200ms

    捎带应答

    在延迟应答的基础上, 我们发现, 很多情况下
    客户端和服务器在应用层也是 “一发一收” 的
    意味着客户端给服务器说了 “How are you”
    服务器也会给客户端回一个 “Fine, thank you”
    那么这个时候ACK就可以搭顺风车, 和服务器回应的 “Fine, thank you” 一起发送给客户端
    这里写图片描述

    面向字节流

    创建一个TCP的socket, 同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区;
    调用write时, 数据会先写入发送缓冲区中;
    如果发送的字节数太大, 会被拆分成多个TCP的数据包发出;
    如果发送的字节数太小, 就会先在缓冲区里等待, 等到缓冲区大小差不多了, 或者到了其他合适的时机再发送出去;
    接收数据的时候, 数据也是从网卡驱动程序到达内核的接收缓冲区;
    然后应用程序可以调用read从接收缓冲区拿数据;
    另一方面, TCP的一个连接, 既有发送缓冲区, 也有接收缓冲区,
    那么对于这一个连接, 既可以读数据, 也可以写数据, 这个概念叫做 全双工

    由于缓冲区的存在, 所以TCP程序的读和写不需要一一匹配
    例如:

    • 写100个字节的数据, 可以调用一次write写100个字节, 也可以调用100次write, 每次写一个字节;
    • 读100个字节数据时, 也完全不需要考虑写的时候是怎么写的, 既可以一次read 100个字节, 也可以一次read一个字节, 重复100次;

    粘包问题

    首先要明确, 粘包问题中的 “包”, 是指应用层的数据包.
    在TCP的协议头中, 没有如同UDP一样的 “报文长度” 字段
    但是有一个序号字段.
    站在传输层的角度, TCP是一个一个报文传过来的. 按照序号排好序放在缓冲区中.
    站在应用层的角度, 看到的只是一串连续的字节数据.
    那么应用程序看到了这一连串的字节数据, 就不知道从哪个部分开始到哪个部分是一个完整的应用层数据包.
    此时数据之间就没有了边界, 就产生了粘包问题

    那么如何避免粘包问题呢?
    归根结底就是一句话, 明确两个包之间的边界

    对于定长的包
    - 保证每次都按固定大小读取即可
    例如上面的Request结构, 是固定大小的, 那么就从缓冲区从头开始按sizeof(Request)依次读取即可

    对于变长的包
    - 可以在数据包的头部, 约定一个数据包总长度的字段, 从而就知道了包的结束位置
    还可以在包和包之间使用明确的分隔符来作为边界(应用层协议, 是程序员自己来定的, 只要保证分隔符不和正文冲突即可)

    对于UDP协议来说, 是否也存在 “粘包问题” 呢?

    对于UDP, 如果还没有向上层交付数据, UDP的报文长度仍然存在.
    同时, UDP是一个一个把数据交付给应用层的, 就有很明确的数据边界.
    站在应用层的角度, 使用UDP的时候, 要么收到完整的UDP报文, 要么不收.
    不会出现收到 “半个” 的情况.

    TCP 异常情况

    • 进程终止: 进程终止会释放文件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别.
    • 机器重启: 和进程终止的情况相同.
    • 机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已经不在了, 就会进行 reset. 即使没有写入操作, TCP自己也内置了一个保活定时器, 会定期询问对方是否还在. 如果对方不在, 也会把连接释放.
    • 另外, 应用层的某些协议, 也有一些这样的检测机制.
      例如HTTP长连接中, 也会定期检测对方的状态.
      例如QQ, 在QQ断线之后, 也会定期尝试重新连接.

    TCP 小结

    为什么TCP这么复杂?

    因为既要保证可靠性, 同时又要尽可能提高性能.

    保证可靠性的机制

    • 校验和
    • 序列号(按序到达)
    • 确认应答
    • 超时重传
    • 连接管理
    • 流量控制
    • 拥塞控制

    提高性能的机制

    • 滑动窗口
    • 快速重传
    • 延迟应答
    • 捎带应答

    定时器

    • 超时重传定时器
    • 保活定时器
    • TIME_WAIT定时器

    基于 TCP 的应用层协议

    HTTP
    HTTPS
    SSH
    Telnet
    FTP
    SMTP

    当然, 也包括我们自己写TCP程序时自定义的应用层协议

    TCP 和 UDP 对比

    我们说了TCP是可靠连接, 那么是不是TCP一定就优于UDP呢?

    TCP和UDP之间的优点和缺点, 不能简单绝对地进行比较
    TCP用于可靠传输的情况, 应用于文件传输, 重要状态更新等场景
    UDP用于对高速传输和实时性要求较高的通信领域
    例如, 早期的QQ, 视频传输等. 另外UDP可以用于广播

    归根结底, TCP和UDP都是一种工具, 什么时机用, 具体怎么用, 还是要根据具体的需求场景去决定.

    展开全文
  • 计算机网络 | 一文搞懂什么是TCP/IP协议

    万次阅读 多人点赞 2019-10-28 12:48:16
    什么是TCP/IP协议? 计算机与网络设备之间如果要相互通信,双方就必须基于相同的方法.比如如何探测到通信目标.由哪一边先发起通信,使用哪种语言进行通信,怎样结束通信等规则都需要事先确定.不同的硬件,操作系统之间的...

    什么是TCP/IP协议?

    计算机与网络设备之间如果要相互通信,双方就必须基于相同的方法.比如如何探测到通信目标.由哪一边先发起通信,使用哪种语言进行通信,怎样结束通信等规则都需要事先确定.不同的硬件,操作系统之间的通信,所有这一切都需要一种规则.而我们就将这种规则称为协议 (protocol).

    image-20191027150025587

    也就是说,TCP/IP 是互联网相关各类协议族的总称。

    TCP/IP 的分层管理

    TCP/IP协议里最重要的一点就是分层。TCP/IP协议族按层次分别为 应用层,传输层,网络层,数据链路层,物理层。当然也有按不同的模型分为4层或者7层的。

    为什么要分层呢?

    把 TCP/IP 协议分层之后,如果后期某个地方设计修改,那么就无需全部替换,只需要将变动的层替换。而且从设计上来说,也变得简单了。处于应用层上的应用可以只考虑分派给自己的任务,而不需要弄清对方在地球上哪个地方,怎样传输,如果确保到达率等问题。

    image-20191027150352733

    如上图所示,我们将TCP/IP分为5层,越靠下越接近硬件。我们由下到上来了解一下这些分层。

    1. 物理层

      该层负责 比特流在节点之间的传输,即负责物理传输,这一层的协议既与链路有关,也与传输的介质有关。通俗来说就是把计算机连接起来的物理手段。

    2. 数据链路层

      控制网络层与物理层之间的通信,主要功能是保证物理线路上进行可靠的数据传递。为了保证传输,从网络层接收到的数据被分割成特定的可被物理层传输的帧。帧是用来移动数据结构的结构包,他不仅包含原始数据,还包含发送方和接收方的物理地址以及纠错和控制信息。其中的地址确定了帧将发送到何处,而纠错和控制信息则确保帧无差错到达。如果在传达数据时,接收点检测到所传数据中有差错,就要通知发送方重发这一帧。

    3. 网络层

      决定如何将数据从发送方路由到接收方。网络层通过综合考虑发送优先权,网络拥塞程度,服务质量以及可选路由的花费等来决定从网络中的A节点到B节点的最佳途径。即建立主机到主机的通信。

    4. 传输层

      该层为两台主机上的应用程序提供端到端的通信。传输层有两个传输协议:TCP(传输控制协议)和 UDP(用户数据报协议)。其中,TCP是一个可靠的面向连接的协议,udp是不可靠的或者说无连接的协议

    5. 应用层

      应用程序收到传输层的数据后,接下来就要进行解读。解读必须事先规定好格式,而应用层就是规定应用程序的数据格式。主要的协议有:HTTP.FTP,Telent等。

    TCP与UDP

    TCP/UDP 都是传输层协议,但是两者具有不同的特效,同时也具有不同的应用场景。

    image-20191027212512703

    面向报文

    面向报文的传输方式是应用层交给UDP多长的报文,UDP发送多长的报文,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。

    面向字节流

    虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应该程序传送的数据块太长,TCP就可以把它划分短一些再传送。

    TCP的三次握手与四次挥手

    具体过程如下:

    • 第一次握手:建立连接。客户端发送连接请求报文段,并将syn(标记位)设置为1,Squence Number(数据包序号)(seq)为x,接下来等待服务端确认,客户端进入SYN_SENT状态(请求连接);

    • 第二次握手:服务端收到客户端的 SYN 报文段,对 SYN 报文段进行确认,设置 ack(确认号)为 x+1(即seq+1 ; 同时自己还要发送 SYN 请求信息,将 SYN 设置为1, seq为 y。服务端将上述所有信息放到 SYN+ACK 报文段中,一并发送给客户端,此时服务器进入 SYN_RECV状态。

      SYN_RECV是指,服务端被动打开后,接收到了客户端的SYN并且发送了ACK时的状态。再进一步接收到客户端的ACK就进入ESTABLISHED状态。

    • 第三次握手:客户端收到服务端的 SYN+ACK(确认符) 报文段;然后将 ACK 设置为 y+1,向服务端发送ACK报文段,这个报文段发送完毕后,客户端和服务端都进入ESTABLISHED(连接成功)状态,完成TCP 的三次握手。

    上面的解释可能有点不好理解,用《图解HTTP》中的一副插图 帮助大家。

    img

    当客户端和服务端通过三次握手建立了 TCP 连接以后,当数据传送完毕,断开连接就需要进行TCP的四次挥手。其四次挥手如下所示:

    • 第一次挥手

      客户端设置seq和 ACK ,向服务器发送一个 FIN(终结)报文段。此时,客户端进入 FIN_WAIT_1 状态,表示客户端没有数据要发送给服务端了。

    • 第二次挥手

      服务端收到了客户端发送的 FIN 报文段,向客户端回了一个 ACK 报文段。

    • 第三次挥手

      服务端向客户端发送FIN 报文段,请求关闭连接,同时服务端进入 LAST_ACK 状态。

    • 第四次挥手

      客户端收到服务端发送的 FIN 报文段后,向服务端发送 ACK 报文段,然后客户端进入 TIME_WAIT 状态。服务端收到客户端的 ACK 报文段以后,就关闭连接。此时,客户端等待 2MSL(指一个片段在网络中最大的存活时间)后依然没有收到回复,则说明服务端已经正常关闭,这样客户端就可以关闭连接了。

    最后再看一下完整的过程:

    img

    如果有大量的连接,每次在连接,关闭都要经历三次握手,四次挥手,这显然会造成性能低下。因此。Http 有一种叫做 长连接(keepalive connections) 的机制。它可以在传输数据后仍保持连接,当客户端需要再次获取数据时,直接使用刚刚空闲下来的连接而无需再次握手。

    img

    一些问题汇总:

    1. 为什么要三次握手?

    为了防止已失效的连接请求报文突然又传送到了服务端,因为产生错误。

    具体解释: “已失效的连接请求报文段”产生情况:

    client 发出的第一个连接请求报文段并没有丢失,而是在某个网络节点长时间滞留,因此导致延误到连接释放以后的某个时间才到达 service。如果没有三次握手,那么此时server收到此失效的连接请求报文段,就误认为是 client再次发出的一个新的连接请求,于是向 client 发出确认报文段,同意建立连接,而此时 client 并没有发出建立连接的情况,因此并不会理会服务端的响应,而service将会一直等待client发送数据,因此就会导致这条连接线路白白浪费。

    如果此时变成两次挥手行不行?

    这个时候需要明白全双工与半双工,再进行回答。比如:

    • 第一次握手: A给B打电话说,你可以听到我说话吗?
    • 第二次握手: B收到了A的信息,然后对A说: 我可以听得到你说话啊,你能听得到我说话吗?
    • 第三次握手: A收到了B的信息,然后说可以的,我要给你发信息啦!

    在三次握手之后,A和B都能确定这么一件事: 我说的话,你能听到; 你说的话,我也能听到。 这样,就可以开始正常通信了,如果是两次,那将无法确定。

    2. 为什么要四次挥手?

    TCP 协议是一种面向连接,可靠,基于字节流的传输层通信协议。TCP 是全双工模式(同一时刻可以同时发送和接收),这就意味着,当主机1发出 FIN 报文段时,只是表示主机1已结没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕;但是,这个时候主机1还是可以接受来自主机2的数据;当主机2返回 ACK报文段时,这个时候就表示主机2也没有数据要发送了,就会告诉主机1,我也没有数据要发送了,之后彼此就会中断这次TCP连接。

    3.为什么要等待 2MSL

    MSL:报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间

    原因如下:

    • 保证TCP协议的全双工连接能够可靠关闭
    • 保证这次连接的重复数据从网络中消息

    第一点: 如果主机1直接 关闭,由于IP协议的不可靠性或者其他网络原因,导致主机2没有收到主机1最后回复的 ACK。那么主机2就会在超时之后继续发送 FIN,此时由于主机1已经关闭,就找不到与重发的 FIN 对应的连接。所以,主机1 不是直接进入 关闭,而是TIME_WAIT 状态。当再次收到 FIN 的时候,能够保证对方收到 ACK ,最后正确关闭连接。

    第二点:如果主机1直接 关闭,然后又再向主机 2 发起一个新连接,我们不能保证这个新连接与刚才关闭的连接端口是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但还是有特殊情况出现;假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中( Lost Duplicate ),那些延迟数据在建立新连接之后才到达主机2,由于新连接和老连接的端口号是一样的,TCP 协议就认为哪个延迟的数据时属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接要在 TIME_WAIT 状态等待两倍 MSL ,保证本次连接的所有数据都从网络中消失。




    参考内容

    <图解HTTP>
    <Android进阶之光-网络篇>
    知乎-TCP 为什么是三次握手,而不是两次或四次?

    展开全文
  • TCP三次握手详解-深入浅出(有图实例演示)

    万次阅读 多人点赞 2018-08-08 21:13:48
    TCP是属于网络分层中的传输层,因为OSI分为层,感觉太麻烦了,所以分为四层就好了,简单。 分层以及每层的协议,如下两张图: TCP三次握手 TCP三次握手简单如下图: TCP三次握手的过程描述: 1.客户...
  • TCP 和 UDP 的区别

    万次阅读 多人点赞 2018-08-04 21:57:42
    TCP TCP 的三次握手 TCP 四次挥手 累计确认 顺序问题和丢包问题 流量控制的问题 拥塞控制的问题 总结及面试问题 前言 前端的面试中经常问的 TCP 和 UDP 的区别,网上也有好多内容,比如 TCP 和 UDP ...
  • 动画:用动画给面试官解释 TCP 三次握手过程

    万次阅读 多人点赞 2019-10-12 07:55:38
    TCP 三次握手过程对于面试是必考的一个,所以不但要掌握 TCP 整个握手的过程,其中有些小细节也更受到面试官的青睐。 对于这部分掌握以及 TCP 的四次挥手,小鹿将会以动画的形式呈现给每个人,这样将复杂的知识简单...
  • 两张动图-彻底明白TCP的三次握手与四次挥手

    万次阅读 多人点赞 2017-06-04 21:53:54
    常用的熟知端口号 应用程序 FTP TFTP TELNET SMTP DNS HTTP SSH MYSQL 熟知端口 21,20 69 23 25 53 80 22 3306 传输层协议 TCP UDP TCP TCP UDP TCP TCP TCP TCP的概述 TCP把连接作为最基本的对象,每一条TCP连接都...
  • 深入理解TCP、UDP协议及两者的区别

    万次阅读 多人点赞 2018-11-14 13:03:24
    一、TCP协议: 位于传输层, 提供可靠的字节流服务。所谓的字节流服务(Byte Stream Service) 是指, 为了方便传输, 将大块数据分割成以报文段(segment) 为单位的数据包进行管理。 而可靠的传输服务是指, 能够...
  • C语言通过socket编程实现TCP通信

    万次阅读 多人点赞 2018-01-02 13:46:27
    服务端客户端通信例子:socket tcp 通信1,socket tcp通信2,udp使用讲解,socket udp通信例子 1. TCP/IP协议 叫做传输控制/网际协议,又叫网络通信协议。实际上,它包含上百个功能的协议,如ICMP(互联网控制信息...
  • TCP、UDP数据包大小的限制

    万次阅读 多人点赞 2016-05-29 10:27:34
    首先要看TCP/IP协议,涉及到四层:链路层,网络层,传输层,应用层。 其中以太网(Ethernet)的数据帧在链路层 IP包在网络层 TCP或UDP包在传输层 TCP或UDP中的数据(Data)在应用层 它们的关系是 数据帧{IP包{...
  • 计算机网络协议(三)——UDP、TCP、Socket

    万次阅读 多人点赞 2019-09-04 08:39:53
    底层网络知识详解:最重要的传输层概述一、UDP协议二、TCP协议2.1 TCP的三次握手 概述 这个专栏的计算机网络协议,我是在极客时间上学习 已经有三万多人购买的刘超老师的趣谈网络协议专栏,讲的特别好,像看小说...
  • TCP协议三次握手和四次握手机制-动画详解

    万次阅读 多人点赞 2018-08-25 20:19:44
    TCP三次握手和四次挥手的问题在面试中是最为常见的考点之一。很多读者都知道三次和四次,但是如果问深入一点,他们往往都无法作出准确回答。 本篇尝试使用动画来对这个知识点进行讲解,期望读者们可以更加简单地地...
  • 面试题:UDP&TCP的区别

    万次阅读 多人点赞 2018-09-01 10:38:20
    UDP协议和TCP协议都是传输层协议。 TCP(Transmission Control Protocol,传输控制协议)提供的是面向连接,可靠的字节流服务。即客户和服务器交换数据前,必须现在双方之间建立一个TCP连接,之后才能传输数据。...
  • TCP 为什么三次握手而不是两次握手(正解版)

    万次阅读 多人点赞 2018-09-19 19:10:58
    TCP 采用三次握手的原因其实非常简单, 远没有大部分博客所描述的那样云山雾绕。
  • LabVIEW通过以太网(TCP)与S7-1200 PLC通信

    万次阅读 多人点赞 2017-09-01 16:31:09
    LabVIEW通过以太网(TCP)与S7-1200 PLC通信 laiping 20170901 摘要:本文介绍LabView采用以太网(TCP)方式与西门子S7-1200PLC通讯 关键字:LabView、S7-1200、TCP、PLC、通信 1、概述 西门子S7-1200 PLC支持...
  • 终于懂了TCP和UDP协议区别

    万次阅读 多人点赞 2020-03-26 12:03:28
    终于懂了TCP和UDP协议区别
  • 动画:用动画给女朋友讲解 TCP 四次分手过程

    万次阅读 多人点赞 2019-10-21 07:57:56
    作者 | 小鹿 来源 | 公众号:小鹿动画学编程 ...很多读者留言说什么时候用动画讲一讲 TCP 四次挥手的过程,为了应大家的要求,今天我们就生动有趣的用动画给大家分享 TCP 四次挥手(分手)过程。 动画:用动画给...
  • QT5实现简单的TCP通信

    万次阅读 多人点赞 2017-04-11 00:43:20
    这段时间用到了QT的TCP通信,做了初步的学习与尝试,编写了一个客户端和服务器基于窗口通信的小例程。 使用QT的网络套接字需要.pro文件中加入一句: QT += network 一、客户端 1、客户端的代码比服务器稍简单,...
  • TCP协议中的三次握手和四次挥手(图解)

    万次阅读 多人点赞 2011-08-07 20:43:02
    建立TCP需要三次握手才能建立,而断开连接则需要四次握手。整个过程如下图所示: 先来看看如何建立连接的。 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源。Client端接收...
  • tcp笔记

    万次阅读 2020-09-06 00:10:03
    【1】TCP滑动窗口控制流量的原理 【2】Windows系统下的TCP参数优化 【3】Linux内核 TCP/IP、Socket参数调优 【4】socket tcp缓冲区大小的默认值、最大值 【5】linux内核调优 【6】/etc/sysctl.conf配置 【7】sysctl...
  • TCP 报文 tcp dup ack 、TCP Retransmission,快速重传,超时重传
  • 什么是TCP粘包?怎么解决这个问题

    万次阅读 多人点赞 2018-12-29 17:47:58
    TCP的socket编程中,发送端和接收端都有成对的socket。发送端为了将多个发往接收端的包,更加高效的的发给接收端,于是采用了优化算法(Nagle算法),将多次间隔较小、数据量较小的数据,合并成一个数据量大的数据...
  • 有100个理由说TCP在某种场景下不好,就有100个理由说TCP在同样的场景了好的不得了,这就好像面对中医或者传统武术一样, 古老陈旧的东西总是被拿来被吹捧或者被打压。 TCP是个30年前陈旧的协议,在计算机网络的编年...
  • TCP三次握手原理

    万次阅读 多人点赞 2019-10-22 09:06:54
    TCP协议\TCP三次握手
  • 终于把TCP协议与UDP协议给整明白了

    万次阅读 多人点赞 2020-07-04 21:35:16
    网络编程有三个要素,分别是IP地址、端口号和通信协议,本文主要讲述的是TCP与UDP这两种通信协议,以及编程的实现。
  • UDP与TCP的对比

    万次阅读 多人点赞 2018-10-01 02:27:08
    (1)TCP协议报头 TCP指传输控制协议,其报头格式如下: TCP协议中的六个标志分别是,URG、ACK、PSH、RST、SYN、FIN。 1)UGR(紧急):UGR=1表示紧急指针字段有效。它告诉系统此报文段有紧急数据,应当尽快传送。从...
  • TCP协议为什么需要三次握手?

    万次阅读 多人点赞 2021-09-02 16:39:14
    TCP实现原理和为什么需要三次握手?两次握手不可以?四次握手不可以?读者可以带着疑问,看一遍本篇博客的详细讲解。首先解释原因之前还是要先复习一下TCP的基本知识和三次握手协议
  • 标准Modbus TCP通信测试工具,两个测试工具主要用于plcModbus TCP通信测试,可分别可是客户端和服务器端 测试环境:西门子SMART s7-200 PLC
  • 网络通信的实体是不同主机之间进程的通信,也就是端到端通信,其过程借助于TCP或者UDP协议,基于端口。 倘若利用TCP协议,则传输前有三次握手,传输后有三次挥手,是一个可靠传输。 倘若利用UDP协议,传输前不需要...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,534,829
精华内容 613,931
关键字:

tcp