1. 程式人生 > >7-客戶端/服務端程式中TIME_WAIT狀態

7-客戶端/服務端程式中TIME_WAIT狀態

  現在我們基於上一篇的客戶端和服務端程式,做一個在關閉連線過程中經常出現TIME_WAIT狀態的實驗(關於TIME_WAIT狀態可以參考這篇文章:23-tcp協議——TIME_WAIT狀態和FIN_WAIT2狀態),修改客戶端和服務端的部分程式碼。



客戶端程式:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define SERV_IP "192.168.0.107"
#define SERV_PORT 10001 int main(void) { int sfd, len,ret; struct sockaddr_in serv_addr; char buf[BUFSIZ]; sfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr); serv_addr.sin_port = htons(SERV_PORT); ret = connect(sfd, (struct
sockaddr *)&serv_addr , sizeof(serv_addr)); if(ret == 0){ puts("connect sucessful"); }else{ puts("connect fail"); return -1; } //迴圈讀寫資料 while (1) { fgets(buf, sizeof(buf), stdin); //將資料寫給伺服器 write(sfd, buf, strlen(buf)); //從伺服器讀取轉換後資料
len = read(sfd, buf, sizeof(buf)); write(STDOUT_FILENO, buf, len); if(buf[0] == 'Q'){ break; } } //關閉連結 close(sfd); return 0; }



服務端程式:

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <sys/types.h>

#define SERV_PORT 10001
#define SERV_IP "192.168.0.107"

int main(void) {
    int sfd, cfd,ret;
    int len, i;
    //BUFSIZ是系統內嵌的一個巨集,用來指定buf大小
    char buf[BUFSIZ], clie_IP[BUFSIZ];
    struct sockaddr_in serv_addr, clie_addr;
    socklen_t clie_addr_len;
    sfd = socket(AF_INET, SOCK_STREAM, 0);
    bzero(&serv_addr, sizeof(serv_addr));      
    serv_addr.sin_family = AF_INET;           
    inet_pton(AF_INET , SERV_IP , &serv_addr.sin_addr.s_addr);
    serv_addr.sin_port = htons(SERV_PORT);              

    //繫結套接字
    ret = bind(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    if(ret < 0){
        perror("bind error");
        return 0;
    }
    //設定連線上限,這裡不會阻塞
    listen(sfd, 64);
    printf("wait for client connect ...\n");
    clie_addr_len = sizeof(clie_addr);
    //阻塞等待客戶端發起連線
    cfd = accept(sfd, (struct sockaddr *)&clie_addr, &clie_addr_len);
    //列印客戶端的ip地址和埠號
    printf("client IP:%s\tport:%d\n", 
            inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, clie_IP, sizeof(clie_IP)), 
            ntohs(clie_addr.sin_port));
    //迴圈處理客戶端的資料請求
    while (1) {
        len = read(cfd, buf, sizeof(buf));
        //read返回0說明對端已經關閉
        if(len == 0){
            break;
        }
        write(STDOUT_FILENO, buf, len);

        //處理客戶端資料,小寫轉大寫
        for (i = 0; i < len; i++){
            buf[i] = toupper(buf[i]);
        }
        //處理完資料,回寫給客戶端
        write(cfd, buf, len);
    }
    //關閉連線
    close(sfd);
    close(cfd);
    return 0;
}



  先啟動./server,然後再啟動./client,然後通過Ctrl+C把服務端終止掉,再啟動./server出現了下面這種情況:
這裡寫圖片描述



  我們發現server再次呼叫bind時出錯了,原因在於雖然服務端終止了,但是服務端和客戶端之間的tcp連線還沒有完全釋放,因此服務端不能再次監聽同樣的埠。我們用netstat命令檢視發現:
這裡寫圖片描述

  當服務端終止時,會關閉套接字描述符並給客戶端傳送FIN,客戶端收到FIN處於CLOSE_WAIT狀態,由於客戶端沒有關閉套接字描述符,所以並不會給服務端傳送FIN,因此服務端還處於FIN_WAIT2狀態。


於是Ctrl+C把客戶端也終止掉,再通過netstat命令檢視服務端發現
這裡寫圖片描述

  客戶端終止時,會關閉套接字描述符並給服務端傳送FIN,服務端收到FIN後會傳送最後一個ACK,並處於TIME_WAIT狀態。對於這一點我們可以通過使用tcpdump抓到的網路資料報來驗證:

這裡寫圖片描述

  tcp規定主動發起關閉連線的一方處於TIME_WAIT,需要等待2MSL時間(RFC規定MSL時間為2分鐘)雙方才會進入CLOSE狀態,所以在TIME_WAIT期間的服務端是不能再次監聽同樣的埠,這意味著處於TIME_WAIT狀態的一方需要經過4分鐘後才能重新建立新的連線,一般在linux中只需等待半分鐘可以再次啟動server了。



這裡寫圖片描述

  等待半分鐘後,用netstat命令檢視發現,此時服務端沒有處於TIME_WAIT狀態,然後再次執行./server就可以成功啟動服務端了(關於TIME_WAIT狀態可以參考:
23-tcp協議——TIME_WAIT狀態和FIN_WAIT2狀態
)。

相關推薦

7-客戶/服務程式TIME_WAIT狀態

  現在我們基於上一篇的客戶端和服務端程式,做一個在關閉連線過程中經常出現TIME_WAIT狀態的實驗(關於TIME_WAIT狀態可以參考這篇文章:23-tcp協議——TIME_WAIT狀態和FIN_WAIT2狀態),修改客戶端和服務端的部分程式碼。 客戶

CentOS 7 安裝NFS服務客戶

寫的權限 防火墻配置 -- tool idm als serve rman 10.10 操作系統:CentOS Linux release 7.2.1511 (Core)NFS服務端安裝:yum install nfs-utils -y創建共享1.在/etc/exports

hessian實現(客戶服務在同一個專案)(轉)

Hessian是基於HTTP的輕量級遠端服務解決方案,Hessian像Rmi一樣,使用二進位制訊息進行客戶端和伺服器端互動。但與其他二進位制遠端呼叫技術(例如Rmi)不同的是,它的二進位制訊息可以移植其他非Java的語言中。 通過Servlet繫結服務 一、建立Hessian程式的4個步驟 定義

程式支付詳解+原始碼(客戶+服務)

今天剛將小程式的支付調通,和大家分享下(坑) 包括小程式端、java伺服器端 和其他方式的微信支付方式區別不大,也都需要經過統一下單、支付結果通知(回撥),具體流程如下: 1、小程式內呼叫登入介面,獲取到使用者的openid,ap

穩定性 耗時 監控原因分析-- dubbo rpc 框架 的線程池,io 連接模型. 客戶,服務

情況 現在 src tcp協議 時間 .cn 關系 1.0 繼續 上次 提到的Nagle算法特性有可能是dubbo調用”網絡耗時高“的始作俑者,後來又仔細看了下dubbo的代碼,發現dubbo在consumer端已經將tcp設置成非延遲(即關閉Nag

H5集成支付寶App支付客戶+服務(java)

XML 服務端 onf response 成功 code default format sim 由於最近項目需要接入第三方開發,支付寶支付,微信支付,OSS圖片上傳以及短信服務。為避免第一次開發支付寶再次花時間查看文檔,今天總結一下接入支付寶的過程,以及接入過程中遇到的問題

go語言實現 tcp客戶/服務

tcpl sem close byte cpc cep 實現 lee n) / server.go /package main import ("bufio""fmt""net""time")

go語言實現udp客戶/服務

rom client nic exit nil 客戶 ddr close udp / server.go /package main import ("fmt""net""os") func checkError

go語言實現unix domain socket 客戶/服務

sock domain tin soc reader ted ips for urn /*server.go */package mainimport ( "bufio" "fmt" &quo

tcp文件下載客戶+服務

des 讀取文件 個人 讀取 循環 用戶輸入 file listen 消息 客戶端: import socket if __name__ == ‘__main__‘: # 創建tcp客戶端socket tcp_client_socket = socket

簡單實現客戶服務互聯通信

fail AI put tin turn 服務端 sizeof tdi sock  /*服務端程序*/#include <stdio.h>#include <stdlib.h>#include<sys/types.h>#include&l

Netty(二):簡單的客戶服務demo

cat println 客戶端連接 監聽端口 rbo 異常 服務端 max auth 使用Java IO實現客戶端服務端 服務端監聽端口 客戶端連接服務端 客戶端循環寫數據到服務端 import java.io.IOException; import java.net.S

Echarts圖表在移動和小程式影響頁面的滾動的解決辦法

Echats圖表在移動端顯示後,當手指在圖表區域內滑動,會影響頁面的滾動。h5頁面沒有親測,小程式頁面,經排查,是因為觸發了touchStart、touchMove和touchEnd方法。 一、h5頁面解決方法 1.如果可以的話,移動端建議使用highCharts代替echarts,感覺

java多執行緒客戶服務實現加密解密

package com.p1; import java.util.HashMap; import java.util.Map; import com.p3.Lockinterface; /*加密解密程式*/ public class Lock implements Lockinterface{

JAVA_TCP客戶服務

服務端: package cn.itcast.tcp.demo; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket;

Java Socket實現客戶服務相互發送文字

Socket是網路程式設計的介面,它抽象成執行緒之間的介面。兩個執行緒,不管它的作業系統,不管它的硬體,只要有Socket介面,在同一主機中或者在不同的主機中都能通訊。我們見到的大大小小的網路程式大多都是通過Socket實現的,比如遊戲伺服器,ftp伺服器,瀏覽器等。所以理解Socket程式設計,是

Oauth2.0客戶服務示例

https://blog.csdn.net/qq_28165595/article/details/80459185   前言前面的理解OAuth2.0認證與客戶端授權碼模式詳解,我們大致瞭解了Oauth2.0授權模式四種的授權碼模式,清楚了授權碼模式的大致流程。這裡簡單的模擬一下基於授權碼模式

winsock 程式設計(簡單客戶&服務通訊實現)

winsock 程式設計(簡單客戶&服務端通訊實現) 看到此處,相信你已經對winsock程式設計有了一定的瞭解,下面給出 簡單的實現。 其中用到的  各個函式詳細說明參考 服務端:初始化winsock-->建立socket-->bind(埠&IP&協議)-

Android開發:使用者註冊登入模組(客戶+服務

1. 前言: 為了方便,將註冊頁面和登入頁面也在一塊。演示: 2.資料庫搭建:MySQL create database test; use test; create table user( user_id int primary key auto_

Netty學習篇(三)--- 客戶 服務實現雙向通訊

客戶端-服務端:客戶端傳送資料到服務端 上篇文章提到,讀寫處理邏輯是在 Bootstrap的handler()方法指定的,上節課寫的如下程式碼: .handler(new ChannelInitializer<Channel>() {