zoukankan      html  css  js  c++  java
  • TCP详解

    1. 数据进入协议栈的封装过程

    2. TCP连接的三次握手

    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 - 没有任何连接状态;

    4. shutdown和close的区别

    shutdown(SHUT_RD):在套接口上不能再发出接受请求;进程仍可往套接口发送数据;套接口接受缓冲区中所有数据被丢弃;再接收到的数据被TCP丢弃,对套接口发送缓冲区无影响.

    shutdown(SHUT_WR)在套接口上不能在发出发送请求;进程仍可以从套接口接受数据;套接口发送缓冲区的内容被发送到对端,后跟正常的TCP连接终止序列(发送FIN);对套接口接收缓冲区无任何影响.

    close(l_onoff=0缺省状态):在套接口上不能在发出发送或接收请求;套接口发送缓冲区中的内容被发送到对端.如果描述字引用计数变为0;在发送完发送缓冲区中的数据后,跟以正常的TCP连接终止序列(发送FIN);套接口接受缓冲区中内容被丢弃

    close(l_onoff = 1, l_linger =0):在套接口上不能再发出发送或接受请求,如果描述子引用计数变为0,RST被发送到对端;连接的状态被置为CLOSED(没有TIME_WAIT状态),套接口发送缓冲区和套接口接受缓冲区的数据被丢弃

    close(l_onoff =1, l_linger != 0):在套接口上不能在发出发送或接收请求;套接口发送缓冲区中的内容被发送到对端.如果描述字引用计数变为0;在发送完发送缓冲区中的数据后,跟以正常的TCP连接终止序列(发送FIN);套接口接受缓冲区中内容被丢弃;如果在连接变成CLOSED状态前延滞时间到,那么close返回EWOULDBLOCK错误.

     

      总结起来就是close关的时候一定是全关;shutdown可以实现半关闭,即只关闭读或者写。

      可参考 http://www.cnblogs.com/Jessy/p/3535612.html 将了内核中的整个执行流程。

    5. 服务端如何判断连接已断开?

    法一:
    当recv()返回值小于等于0时,socket连接断开。但是还需要判断 errno是否等于 EINTR,如果errno == EINTR 则说明recv函数是由于程序接收到信号后返回的,socket连接还是正常的,不应close掉socket连接。
     
    法二:
      struct tcp_info info; 
      int len=sizeof(info); 
      getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len); 
      if((info.tcpi_state==TCP_ESTABLISHED))  则说明未断开  else 断开


    法三:
    若使用了select等系统函数,若远端断开,则select返回1,recv返回0则断开。其他注意事项同法一。

    法四:
    int keepAlive = 1; // 开启keepalive属性
    int keepIdle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测 
    int keepInterval = 5; // 探测时发包的时间间隔为5 秒
    int keepCount = 3; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发.

    setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));
    setsockopt(rs, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));
    setsockopt(rs, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
    setsockopt(rs, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));

    设置后,若断开,则在使用该socket读写时立即失败,并返回ETIMEDOUT错误

    法五:
    自己实现一个心跳检测,一定时间内未收到自定义的心跳包则标记为已断开。

    参见: http://blog.csdn.net/hnlyyk/article/details/50819823?ref=myread 

    6. MTU和MSS

    本文用到的抓包工具为wireshark,它的前身是赫赫有名的Ethereal。wireshark以太网帧的封包格式为:

    ----------------------------------------------------------------------------------------------------

    Frame=Ethernet Header +IP Header +TCP Header +TCP Segment Data

    ----------------------------------------------------------------------------------------------------

    (1)Ethernet Header =14 Byte =Dst Physical Address(6 Byte)+ Src Physical Address(6 Byte)+Type(2 Byte),以太网帧头以下称之为数据帧。

    (2)IP Header =20 Byte(without options field),数据在IP层称为Datagram,分片称为Fragment

    (3)TCP Header = 20 Byte(without options field),数据在TCP层称为Stream,分段称为Segment(UDP中称为Message)。

    (4)54个字节后为TCP数据负载部分(Data Portion),即应用层用户数据。

    Ethernet Header以下的IP数据报最大传输单位为MTU(Maximum Transmission Unit,Effect of short board),对于大多数使用以太网的局域网来说,MTU=1500。

    TCP数据包每次能够传输的最大数据分段为MSS,为了达到最佳的传输效能,在建立TCP连接时双方将协商MSS值——双方提供的MSS值中的最小值为这次连接的最大MSS值。MSS往往基于MTU计算出来,通常MSS=MTU-sizeof(IP Header)-sizeof(TCP Header)=1500-20-20=1460。

    这样,数据经过本地TCP层分段后,交给本地IP层,在本地IP层就不需要分片了。但是在下一跳路由(Next Hop)的邻居路由器上可能发生IP分片!因为路由器的网卡的MTU可能小于需要转发的IP数据报的大小。这时候,在路由器上可能发生两种情况:

    (1)如果源发送端设置了这个IP数据包可以分片(May FragmentDF=0),路由器将IP数据报分片后转发。

    (2)如果源发送端设置了这个IP数据报不可以分片(Don’t FragmentDF=1),路由器将IP数据报丢弃,并发送ICMP分片错误消息给源发送端。

    关于MTU的探测,参考《Path MTU discovery》。我们可以通过基于ICMP协议的ping命令来探测从本机出发到目标机器上路由上的MTU,详见下文。

  • 相关阅读:
    700. Search in a Binary Search Tree
    100. Same Tree
    543. Diameter of Binary Tree
    257. Binary Tree Paths
    572. Subtree of Another Tree
    226. Invert Binary Tree
    104. Maximum Depth of Binary Tree
    1、解决sublime打开文档,出现中文乱码问题
    移植seetafaceengine-master、opencv到ARM板
    ubuntu16.04-交叉编译-SeetaFaceEngine-master
  • 原文地址:https://www.cnblogs.com/foreverstars/p/4764474.html
Copyright © 2011-2022 走看看