最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

CLOSE_WAIT狀態(tài)解決方案

 更新時(shí)間:2021年08月16日 15:40:39   作者:libaineu2004  
這篇文章主要介紹了CLOSE_WAIT狀態(tài)解決方案,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下

這個(gè)問(wèn)題之前沒(méi)有怎么留意過(guò),是最近在面試過(guò)程中遇到的一個(gè)問(wèn)題,面了兩家公司,兩家公司竟然都面到到了這個(gè)問(wèn)題,不得不使我開(kāi)始關(guān)注這個(gè)問(wèn)題。說(shuō)起CLOSE_WAIT狀態(tài),如果不知道的話,還是先瞧一下TCP的狀態(tài)轉(zhuǎn)移圖吧。

 

關(guān)閉socket分為主動(dòng)關(guān)閉(Active closure)和被動(dòng)關(guān)閉(Passive closure)兩種情況。前者是指有本地主機(jī)主動(dòng)發(fā)起的關(guān)閉;而后者則是指本地主機(jī)檢測(cè)到遠(yuǎn)程主機(jī)發(fā)起關(guān)閉之后,作出回應(yīng),從而關(guān)閉整個(gè)連接。將關(guān)閉部分的狀態(tài)轉(zhuǎn)移摘出來(lái),就得到了下圖:

TCP 狀態(tài)變化

產(chǎn)生原因
通過(guò)圖上,我們來(lái)分析,什么情況下,連接處于CLOSE_WAIT狀態(tài)呢?
在被動(dòng)關(guān)閉連接情況下,在已經(jīng)接收到FIN,但是還沒(méi)有發(fā)送自己的FIN的時(shí)刻,連接處于CLOSE_WAIT狀態(tài)。
通常來(lái)講,CLOSE_WAIT狀態(tài)的持續(xù)時(shí)間應(yīng)該很短,正如SYN_RCVD狀態(tài)。但是在一些特殊情況下,就會(huì)出現(xiàn)連接長(zhǎng)時(shí)間處于CLOSE_WAIT狀態(tài)的情況。

出現(xiàn)大量close_wait的現(xiàn)象,主要原因是某種情況下對(duì)方關(guān)閉了socket鏈接,但是我方忙與讀或者寫,沒(méi)有關(guān)閉連接。代碼需要判斷socket,一旦讀到0,斷開(kāi)連接,read返回負(fù),檢查一下errno,如果不是AGAIN,就斷開(kāi)連接。

參考資料4中描述,通過(guò)發(fā)送SYN-FIN報(bào)文來(lái)達(dá)到產(chǎn)生CLOSE_WAIT狀態(tài)連接,沒(méi)有進(jìn)行具體實(shí)驗(yàn)。不過(guò)個(gè)人認(rèn)為協(xié)議棧會(huì)丟棄這種非法報(bào)文,感興趣的同學(xué)可以測(cè)試一下,然后把結(jié)果告訴我;-)

為了更加清楚的說(shuō)明這個(gè)問(wèn)題,我們寫一個(gè)測(cè)試程序,注意這個(gè)測(cè)試程序是有缺陷的。
只要我們構(gòu)造一種情況,使得對(duì)方關(guān)閉了socket,我們還在read,或者是直接不關(guān)閉socket就會(huì)構(gòu)造這樣的情況。

server.c:

#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
 
#define MAXLINE 80
#define SERV_PORT 8000
 
int main(void)
{
    struct sockaddr_in servaddr, cliaddr;
    socklen_t cliaddr_len;
    int listenfd, connfd;
    char buf[MAXLINE];
    char str[INET_ADDRSTRLEN];
    int i, n;
 
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
 
        int opt = 1;
        setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
 
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);
    
    bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
 
    listen(listenfd, 20);
 
    printf("Accepting connections ...\n");
    while (1) {
        cliaddr_len = sizeof(cliaddr);
        connfd = accept(listenfd, 
                (struct sockaddr *)&cliaddr, &cliaddr_len);
        //while (1) 
                {
            n = read(connfd, buf, MAXLINE);
            if (n == 0) {
                printf("the other side has been closed.\n");
                break;
            }
            printf("received from %s at PORT %d\n",
                   inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
                   ntohs(cliaddr.sin_port));
    
            for (i = 0; i < n; i++)
                buf[i] = toupper(buf[i]);
            write(connfd, buf, n);
        }
        //這里故意不關(guān)閉socket,或者是在close之前加上一個(gè)sleep都可以
        //sleep(5);
        //close(connfd);
    }
}

client.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
 
#define MAXLINE 80
#define SERV_PORT 8000
 
int main(int argc, char *argv[])
{
    struct sockaddr_in servaddr;
    char buf[MAXLINE];
    int sockfd, n;
    char *str;
    
    if (argc != 2) {
        fputs("usage: ./client message\n", stderr);
        exit(1);
    }
    str = argv[1];
    
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
 
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
    servaddr.sin_port = htons(SERV_PORT);
    
    connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
 
    write(sockfd, str, strlen(str));
 
    n = read(sockfd, buf, MAXLINE);
    printf("Response from server:\n");
    write(STDOUT_FILENO, buf, n);
    write(STDOUT_FILENO, "\n", 1);
 
    close(sockfd);
    return 0;
}

結(jié)果如下:

debian-wangyao:~$ ./client a
Response from server:
A
debian-wangyao:~$ ./client b
Response from server:
B
debian-wangyao:~$ ./client c
Response from server:
C
debian-wangyao:~$ netstat -antp | grep CLOSE_WAIT
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        1      0 127.0.0.1:8000          127.0.0.1:58309         CLOSE_WAIT  6979/server     
tcp        1      0 127.0.0.1:8000          127.0.0.1:58308         CLOSE_WAIT  6979/server     
tcp        1      0 127.0.0.1:8000          127.0.0.1:58307         CLOSE_WAIT  6979/server  

解決方法
基本的思想就是要檢測(cè)出對(duì)方已經(jīng)關(guān)閉的socket,然后關(guān)閉它。

1.代碼需要判斷socket,一旦read返回0,斷開(kāi)連接,read返回負(fù),檢查一下errno,如果不是AGAIN,也斷開(kāi)連接。(注:在UNP 7.5節(jié)的圖7.6中,可以看到使用select能夠檢測(cè)出對(duì)方發(fā)送了FIN,再根據(jù)這條規(guī)則就可以處理CLOSE_WAIT的連接)

2.給每一個(gè)socket設(shè)置一個(gè)時(shí)間戳last_update,每接收或者是發(fā)送成功數(shù)據(jù),就用當(dāng)前時(shí)間更新這個(gè)時(shí)間戳。定期檢查所有的時(shí)間戳,如果時(shí)間戳與當(dāng)前時(shí)間差值超過(guò)一定的閾值,就關(guān)閉這個(gè)socket。

3.使用一個(gè)Heart-Beat線程,定期向socket發(fā)送指定格式的心跳數(shù)據(jù)包,如果接收到對(duì)方的RST報(bào)文,說(shuō)明對(duì)方已經(jīng)關(guān)閉了socket,那么我們也關(guān)閉這個(gè)socket。

4.設(shè)置SO_KEEPALIVE選項(xiàng),并修改內(nèi)核參數(shù)

前提是啟用socket的KEEPALIVE機(jī)制:
//啟用socket連接的KEEPALIVE
int iKeepAlive = 1;
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *)&iKeepAlive, sizeof(iKeepAlive));

tcp_keepalive_intvl (integer; default: 75; since Linux 2.4)
The number of seconds between TCP keep-alive probes.

tcp_keepalive_probes (integer; default: 9; since Linux 2.2)
The  maximum  number  of  TCP  keep-alive  probes  to  send before giving up and killing the connection if no response is obtained from the other end.

tcp_keepalive_time (integer; default: 7200; since Linux 2.2)
The number of seconds a connection needs to be idle before TCP begins sending out  keep-alive  probes.   Keep-alives  are only  sent when the SO_KEEPALIVE socket option is enabled.  The default value is 7200 seconds (2 hours).  An idle connec‐tion is terminated after approximately an additional 11 minutes (9 probes an interval of 75  seconds  apart)  when  keep-alive is enabled.

echo 120 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 2 > /proc/sys/net/ipv4/tcp_keepalive_intvl
echo 1 > /proc/sys/net/ipv4/tcp_keepalive_probes

除了修改內(nèi)核參數(shù)外,可以使用setsockopt修改socket參數(shù),參考man 7 socket。

int KeepAliveProbes=1;
int KeepAliveIntvl=2;
int KeepAliveTime=120;
setsockopt(s, IPPROTO_TCP, TCP_KEEPCNT, (void *)&KeepAliveProbes, sizeof(KeepAliveProbes));
setsockopt(s, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&KeepAliveTime, sizeof(KeepAliveTime));
setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&KeepAliveIntvl, sizeof(KeepAliveIntvl));

到此這篇關(guān)于CLOSE_WAIT狀態(tài)解決方案的文章就介紹到這了,更多相關(guān)CLOSE_WAIT狀態(tài)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++ Boost Graph算法超詳細(xì)精講

    C++ Boost Graph算法超詳細(xì)精講

    這篇文章主要介紹了C++ Boost Graph算法,我門嘗試使用Boost.Graph庫(kù)來(lái)運(yùn)行Goldberg的最大流算法。 Boost.Graph將其稱為push_relabel_max_flow
    2022-10-10
  • C++實(shí)現(xiàn)插入排序?qū)φ麛?shù)數(shù)組排序

    C++實(shí)現(xiàn)插入排序?qū)φ麛?shù)數(shù)組排序

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)插入排序?qū)φ麛?shù)數(shù)組排序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • Qt學(xué)習(xí)筆記之QPalette調(diào)色板類

    Qt學(xué)習(xí)筆記之QPalette調(diào)色板類

    這篇文章主要為大家詳細(xì)介紹了Qt學(xué)習(xí)筆記之QPalette調(diào)色板類,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • C++中內(nèi)存池的簡(jiǎn)單原理及實(shí)現(xiàn)詳解

    C++中內(nèi)存池的簡(jiǎn)單原理及實(shí)現(xiàn)詳解

    內(nèi)存池的思想是,在真正使用內(nèi)存之前,預(yù)先申請(qǐng)分配一定數(shù)量、大小預(yù)設(shè)的內(nèi)存塊留作備用。本文主要來(lái)和大家聊聊內(nèi)存池的簡(jiǎn)單原理及實(shí)現(xiàn),希望對(duì)大家有所幫助
    2023-03-03
  • C++?函數(shù)重載背后的原理

    C++?函數(shù)重載背后的原理

    這篇文章主要介紹了C++?函數(shù)重載背后的原理,我們不僅僅需要學(xué)會(huì)重載的使用,更要了解C++為什么支持函數(shù)重載,下面我們一起進(jìn)入文章學(xué)習(xí)該內(nèi)容吧
    2022-05-05
  • C/C++中的內(nèi)存管理小結(jié)

    C/C++中的內(nèi)存管理小結(jié)

    這篇文章主要介紹了C/C++中的內(nèi)存管理小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • 詳解C++17中類模板參數(shù)推導(dǎo)的使用

    詳解C++17中類模板參數(shù)推導(dǎo)的使用

    自C++17起就通過(guò)使用類模板參數(shù)推導(dǎo),只要編譯器能根據(jù)初始值推導(dǎo)出所有模板參數(shù),那么就可以不指明參數(shù),下面我們就來(lái)看看C++17中類模板參數(shù)推導(dǎo)的具體使用吧
    2024-03-03
  • 深入理解C語(yǔ)言中編譯相關(guān)的常見(jiàn)錯(cuò)誤

    深入理解C語(yǔ)言中編譯相關(guān)的常見(jiàn)錯(cuò)誤

    本篇文章是對(duì)C語(yǔ)言中編譯相關(guān)的常見(jiàn)錯(cuò)誤進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • c++11多種格式時(shí)間轉(zhuǎn)化為字符串的方法實(shí)現(xiàn)

    c++11多種格式時(shí)間轉(zhuǎn)化為字符串的方法實(shí)現(xiàn)

    本文主要介紹了c++11多種格式時(shí)間轉(zhuǎn)化為字符串的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • C++的new和delete詳解

    C++的new和delete詳解

    這篇文章主要介紹的是C++的new和delete,可以這么理解 new相當(dāng)于是malloc 、delete相當(dāng)于是free,下面我們就來(lái)詳情介紹,,需要的朋友可以參一考
    2021-09-09

最新評(píng)論

天气| 高尔夫| 盐亭县| 西城区| 八宿县| 都昌县| 济源市| 隆尧县| 南汇区| 凌海市| 安泽县| 商城县| 荔浦县| 长岭县| 丰镇市| 光山县| 车致| 宜州市| 固始县| 凉城县| 平塘县| 承德县| 社会| 灵宝市| 康乐县| 灵璧县| 丁青县| 辽源市| 邵阳县| 博乐市| 舟曲县| 云龙县| 定州市| 平山县| 陵川县| 正蓝旗| 泸州市| 高陵县| 黎城县| 朔州市| 大方县|