zoukankan      html  css  js  c++  java
  • linux 网络的连接

    linux 网络的连接

    标签(空格分隔): 网络

    原博客:https://blog.csdn.net/a3192048/article/details/82689984


    查看连接

    netstat -na | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
    

    字段

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

    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连接就建立了,客户端和服务器可以愉快地玩耍了。只要通信双方没有一方发出连接释放的请求,连接就将一直保持。

    image

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

    由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个

    FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

    (1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。

    (2) 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。

    (3) 服务器关闭客户端的连接,发送一个FIN给客户端。

    (4) 客户端发回ACK报文确认,并将确认序号设置为收到序号加1。

    image

    CLOSED

    服务端和客户端都用
    表示初始状态

    LISTEN

    服务端用
    表示服务器端的某个socket 处于监听状态
    可以接受连接了

    SYN_RECV

    服务端用
    这个状态表示接受到了SYN报文,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂

    基本上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。

    什么是SYN Flood攻击?
    SYN Flood (SYN洪水) 是种典型的DoS (Denial of Service,拒绝服务) 攻击。效果就是服务器TCP连接资源耗尽,停止响应正常的TCP连接请求。
    TCP SYN Flood是一种常见,而且有效的远端(远程)拒绝服务(Denial of Service)攻击方式,它通过一定的操作破坏TCP三次握手建立正常连接,占用并耗费系统资源,使得提供TCP服务的主机系统无法正常工作。由于TCP SYN Flood是透过网路底层对服务器Server进行攻击的
    
    解决办法
    
    + 增加未完成连接队列(q0)的最大长度。
    net.ipv4.tcp_max_syn_backlog = 65536
    
    + 启动SYN_cookie
    net.ipv4.tcp_syncookies = 1
    
    这些是被动的方法,治标不治本。而且加大了服务器的负担,但是可以避免被拒绝攻击(只是减缓)
    治本的方法是在防火墙上做手脚。但是现在能在一定程度上防住syn flood攻击的防火墙都不便宜。并且把这个命令加入”/etc/rc.d/rc.local”文件中
    
    设置 iptables 来防止攻击
     iptables -A FORWARD -p tcp –syn -m limit –limit 1/s -j ACCEPT
    

    SYN_SENT

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

    ESTABLISHED

    客户端、服务器
    表示连接已经建立

    出现 3次握手的结局
    出现 4次解手的开始

    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状态,发生的概率很小。

    另一种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送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可用状态了。

    image


    nginx产生过多的wait

    LOSE_WAIT产生的原因是客户端B主动关闭,
    服务器A收到FIN包,应用层却没有做出关闭操作引起的。
    CLOSE_WAIT在Nginx上面的产生原因还是因为Nagle’s算法加Nginx本身EPOLL的ET触发模式导致。

    ET出发模式在数据就绪的时候会触发一次回调操作,Nagle’s算法会累积TCP包,如果最后的数据包和

    FIN包被Nagle’s算法合并,会导致EPOLL的ET模式只触发一次。
    然而在应用层的SOCKET是读取返回0才代表链接关闭,
    而读取这次合并的数据包时是不返回0的,
    然后SOCKET以后都不会触发事件,
    所以导致应用层没有关闭SOCKET,
    从而产生大量的CLOSE_WAIT状态链接。
    关闭TCP_NODELAY,在Nginx配置中加上

    tcp_nodelay on;
    
    
    
    ## 快速回收time_wait
    net.ipv4.tcp_tw_recycle = 1
    
    ## 让TIME_WAIT状态可以重用,这样即使TIME_WAIT占满了所有端口,也不会拒绝新的请求造成障碍
    
    ## time_wait 尽快回收
    net.ipv4.tcp_tw_reuse = 1
    
  • 相关阅读:
    【2】Java包装类
    【1】Java异常
    【10】Java多态:内部类
    【9】Java多态:接口
    【8】Java多态:抽象类(abstract关键字)
    【7】Java多态:向上转型、向下转型、instanceof运算符
    【6】Java单例模式
    元素定位工具:Chrome浏览器ChroPath插件
    linux添加环境变量
    php导出数据到多个csv并打包压缩
  • 原文地址:https://www.cnblogs.com/hywhyme/p/14564998.html
Copyright © 2011-2022 走看看