TCP/IP、UDP、HTTP、SOCKET详解(非原创)

文章大纲

  1. 网络OSI七层及各层做用
  2. TCP与UDP基本介绍
  3. TCP链接过程详解
  4. SOCKET原理与链接详解
 
 

1、网络OSI七层及各层做用

 
  1. 应用层:文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet
  2. 表示层:数据格式化,代码转换,数据加密 没有协议
  3. 会话层:解除或创建与别的接点的联系 没有协议
  4. 传输层:提供端对端的接口 TCP,UDP
  5. 网络层:为数据包选择路由 IP,ICMP,RIP,OSPF,BGP,IGMP
  6. 数据链路层:传输有地址的帧以及错误检测功能 SLIP,CSLIP,PPP,ARP,RARP,MTU
  7. 物理层:以二进制数据形式在物理媒体上传输数据 ISO2110,IEEE802,IEEE802.2

2、TCP与UDP基本介绍

TCP
  TCP:Transmission Control Protocol 传输控制协议TCP是一种面向链接(链接导向)的、可靠的、基于字节流的运输层(Transport layer)通讯协议。 特色: 面向链接的协议,数据传输必需要通过三次握手创建链接,因此在TCP中须要链接时间。 传输数据大小限制,一旦链接创建,双方能够按统一的格式传输大的数据。 一个可靠的协议,确保接收方彻底正确地获取发送方所发送的所有数据。html

UDP
  UDP: User Datagram Protocol的简称, 中文名是用户数据包协议,是 OSI 参考模型中一种无链接的传输层协议,提供面向事务的简单不可靠信息传送服务。 特色: 每一个数据报中都给出了完整的地址信息,所以无须要创建发送方和接收方的链接。 UDP传输数据时是有大小限制的,每一个被传输的数据报必须限定在64KB以内。 UDP是一个不可靠的协议,发送方所发送的数据报并不必定以相同的次序到达接收方。服务器

3、TCP链接过程详解

基本参数介绍

LISTEN:侦听来自远方的TCP端口的链接请求
SYN-SENT:再发送链接请求后等待匹配的链接请求(客户端)
SYN-RECEIVED:再收到和发送一个链接请求后等待对方对链接请求的确认(服务器)
ESTABLISHED:表明一个打开的链接
FIN-WAIT-1:等待远程TCP链接中断请求,或先前的链接中断请求的确认
FIN-WAIT-2:从远程TCP等待链接中断请求
CLOSE-WAIT:等待从本地用户发来的链接中断请求
CLOSING:等待远程TCP对链接中断的确认
LAST-ACK:等待原来的发向远程TCP的链接中断请求的确认
TIME-WAIT:等待足够的时间以确保远程TCP接收到链接中断请求的确认
CLOSED:没有任何链接状态网络

主动端可能出现的状态:FIN_WAIT一、FIN_WAIT二、CLOSING、TIME_WAIT
被动端可能出现的状态:CLOSE_WAIT LAST_ACK并发

客户端的状态能够用以下的流程来表示:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSEDsocket

服务器的状态能够用以下的流程来表示:
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSEDtcp

舒适提示:
(1)主动端出现大量的FIN_WAIT1时须要注意网络是否畅通、出现大量的FIN_WAIT2须要仔细检查程序为什么迟迟收不到对端的FIN(多是主动方或者被动方的bug)、出现大量的TIME_WAIT须要注意系统的并发量/socket句柄资源/内存使用/端口号资源等。
(2)被动端出现大量的 CLOSE_WAIT 须要仔细检查为什么本身迟迟不肯调用close关闭链接(多是bug,socket打开用完没有关闭)测试

状态迁移
创建链接时的状态变迁
一开始,创建链接以前服务器和客户端的状态都为CLOSED。服务器建立socket后开始监听,变为LISTEN状态。客户端请求创建链接,向服务器发送SYN报文,客户端的状态变为SYN_SENT。服务器收到客户端的报文后向客户端发送ACK和SYN报文,此时服务器的状态变为SYN_RCVD。而后,客户端收到ACK、SYN,就向服务器发送ACK,客户端状态变为ESTABLISHED,服务器收到客户端的ACK后也变为ESTABLISHED。此时,3次握手完成,链接创建!加密

断开链接时的状态变迁
因为tcp链接是全双工的,断开链接会比创建链接麻烦一点点。客户端先向服务器发送FIN报文,请求断开链接,其状态变为FIN_WAIT1。服务器收到FIN后向客户端发生ACK,服务器状态变为CLOSE_WAIT。客户端收到ACK后就进入FIN_WAIT2状态。此时链接已经断开了一半了。若是服务器还有数据要发送给客户端,就会继续发送。直到发完了,就发送FIN报文,此时服务器进入LAST_ACK状态。客户端收到服务器的FIN后,立刻发送ACK给服务器,此时客户端进入TIME_WAIT状态,再过了2MSL长的时间后进入CLOSED状态。服务器收到客户端的ACK就进入CLOSED状态。
至此,还有一个状态没有说起:CLOSING状态。CLOSING状态表示客户端发生了FIN,但没有收到服务器的ACK,却收到了服务器的FIN。这种状况发生在服务器发送的ACK丢包的时候,由于网络传输有时会有意外。url

tcp链接创建(tcp三握手)

  TCP链接的创建采用客户-服务器模式:主动发起链接创建的应用进程叫作客户,被动等待链接创建的应用进程叫作服务器。
  链接创建阶段:
  第一次握手:客户端的应用进程主动打开,并向服务端发出请求报文段。其首部中:SYN=1,seq=x。
  第二次握手:服务器应用进程被动打开。若赞成客户端的请求,则发回确认报文,其首部中:SYN=1,ACK=1,ack=x+1,seq=y。
  第三次握手:客户端收到确认报文以后,通知上层应用进程链接已创建,并向服务器发出确认报文,其首部:ACK=1,ack=y+1。当服务器收到客户端的确认报文以后,也通知其上层应用进程链接已创建。
在这个过程当中,通讯双方的状态以下图,其中CLOSED:关闭状态、LISTEN:收听状态、SYN-SENT:同步已发送、SYN-RCVD:同步收到、ESTAB-LISHED:链接已创建
至此,TCP链接就创建了,客户端和服务器能够愉快地玩耍了。只要通讯双方没有一方发出链接释放的请求,链接就将一直保持。spa

 

 
 

tcp链接终止协议*(tcp四挥手)

  因为TCP链接是全双工的,所以每一个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的链接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP链接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另外一方执行被动关闭。
(1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
(2) 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN同样,一个FIN将占用一个序号。
(3) 服务器关闭客户端的链接,发送一个FIN给客户端。
(4) 客户端发回ACK报文确认,并将确认序号设置为收到序号加1。

 

 
 

为何客户端最后还要等待2MSL?

  MSL(Maximum Segment Lifetime),TCP容许不一样的实现能够设置不一样的MSL值。
  第一,保证客户端发送的最后一个ACK报文可以到达服务器,由于这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端尚未给我回应,应该是我发送的请求断开报文它没有收到,因而服务器又会从新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,而且会重启2MSL计时器
  第二,防止相似与“三次握手”中提到了的“已经失效的链接请求报文段”出如今本链接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可使本链接持续的时间内所产生的全部报文段都从网络中消失。这样新的链接中不会出现旧链接的请求报文。
  为何创建链接是三次握手,关闭链接确是四次挥手呢?
  创建链接的时候,服务器在LISTEN状态下,收到创建链接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭链接时,服务器收到对方的FIN报文时,仅仅表示对方再也不发送数据了可是还能接收数据,而本身也未必所有数据都发送给对方了,因此己方能够当即关闭,也能够发送一些数据给对方后,再发送FIN报文给对方来表示赞成如今关闭链接,所以,己方ACK和FIN通常都会分开发送,从而致使多了一次。

参数详解

CLOSED
  这个没什么好说的了,表示初始状态。

LISTEN
  这个也是很是容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,能够接受链接了。

SYN_RCVD
  这个状态表示接受到了SYN报文,在正常状况下,这个状态是服务器端的SOCKET在创建TCP链接时的三次握手会话过程当中的一个中间状态,很短暂,基本上用netstat你是很难看到这种状态的,除非你特地写了一个客户端测试程序,故意将三次TCP握手过程当中最后一个ACK报文不予发送。所以这种状态时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。

SYN_SENT
  这个状态与SYN_RCVD遥想呼应,当客户端SOCKET执行CONNECT链接时,它首先发送SYN报文,所以也随即它会进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。

ESTABLISHED
  这个容易理解了,表示链接已经创建了。

FIN_WAIT_1
  这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态其实是当SOCKET在ESTABLISHED状态时,它想主动关闭链接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,固然在实际的正常状况下,不管对方何种状况下,都应该立刻回应ACK报文,因此FIN_WAIT_1状态通常是比较难见到的,而FIN_WAIT_2状态还有时经常能够用netstat看到。

FIN_WAIT_2
  上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半链接,也即有一方要求close链接,但另外还告诉对方,我暂时还有点数据须要传送给你,稍后再关闭链接这就是著名的半关闭的状态了,这是在关闭链接时,客户端和服务器两次握手以后的状态。在这个状态下,应用程序还有接受数据的能力,可是已经没法发送数据,可是也有一种多是,客户端一直处于FIN_WAIT_2状态,而服务器则一直处于WAIT_CLOSE状态,而直到应用层来决定关闭这个状态

TIME_WAIT
  表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后便可回到CLOSED可用状态了。若是FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,能够直接进入到TIME_WAIT状态,而无须通过FIN_WAIT_2状态。

CLOSING
  这里先说一下另外一种状态(同时打开)
  RST是另外一种关闭链接的方式,应用程序应该能够判断RST包的真实性,便是否为异常停止。而同时打开和同时关闭则是两种特殊的TCP状态,发生的几率很小。
下面说closing状态 ,这种状态比较特殊,实际状况中应该是不多见,属于一种比较罕见的例外状态。正常状况下,当你发送FIN报文后,按理来讲是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。可是CLOSING状态表示你发送FIN报文后,并无收到对方的ACK报文,反而却也收到了对方的FIN报文。什么状况下会出现此种状况呢?其实细想一下,也不可贵出结论:那就是若是双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的状况,也就会出现CLOSING状态,表示双方都正在关闭SOCKET链接。

CLOSE_WAIT
  这种状态的含义实际上是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给本身,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正须要考虑的事情是查看你是否还有数据发送给对方,若是没有的话,那么你也就能够close这个SOCKET,发送FIN报文给对方,也即关闭链接。因此你在CLOSE_WAIT状态下,须要完成的事情是等待你去关闭链接。

LAST_ACK
  这个状态仍是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也便可以进入到CLOSED可用状态了。

4、SOCKET原理与链接详解

SOCKET原理

  Socket socket的英文原义是“孔”或“插座”。做为4BDS UNIX的进程通讯机制,取后一种意思。一般也称做“套接字”,用于描述IP地址和端口,是一个通讯链的句柄(引用)。 每一个插座就是一个应用程序。 细节 不一样的通讯规则须要定义不一样的插座。 UDP:DatagramSocket 、 DatagramPacket TCP:ServerSocket 、Socket

创建SOCKET链接

  创建Socket链接至少须要一对套接字,其中一个运行于客户端,称为ClientSocket ,另外一个运行于服务器端,称为ServerSocket 。套接字之间的链接过程分为三个步骤:服务器监听,客户端请求,链接确认。
  服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待链接的状态,实时监控网络状态,等待客户端的链接请求。
  客户端请求:指客户端的套接字提出链接请求,要链接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要链接的服务器的套接字,指出服务器端套接字的地址和端口号,而后就向服务器端套接字提出链接请求。
  链接确认:当服务器端套接字监听到或者说接收到客户端套接字的链接请求时,就响应客户端套接字的请求,创建一个新的线程,把服务器端套接字的描述发 给客户端,一旦客户端确认了此描述,双方就正式创建链接。而服务器端套接字继续处于监听状态,继续接收其余客户端套接字的链接请求。
链接实例

 
 

 

参考文章

    1. https://blog.csdn.net/qq_31337311/article/details/80781273
    2. https://www.cnblogs.com/A0926/p/5174488.html
    3. https://blog.csdn.net/hkhl_235/article/details/79721645
    4. https://www.cnblogs.com/i6010/articles/6396349.html
    5. https://blog.csdn.net/u011774517/article/details/67631439
相关文章
相关标签/搜索