当前位置: 首页 > article >正文

TIME_WAIT状态套接字重新使用

《TIME_WAIT相关知识》里边有相关理论知识。
《TIME_WAIT状态TCP连接导致套接字无法重用实验》有相关实验。

现代Linux的TCP协议栈已经做了许多升级,所以可以让我们直接重用TIME_WAIT状态套接字而不会引起问题。下边是优化的内容:

1.新连接的SYN告知序列号比原来TIME_WAIT老连接末序列号要大,所以就可以通过序列号分辨出来新老连接。
2.开启tcp_timestamps,这样就让新连接时间戳比旧连接时间戳大,这样可以通过检查时间戳来判断新老连接。

在这样两重优化下,重用TIME_WAIT状态连接就不会产生任何问题了。

int on = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

SO_REUSEADDR用来告诉操作系统内核,如果端口已被占用,但是 TCP 连接状态位于 TIME_WAIT ,可以重用端口。这段代码需要放到socket函数和bind函数之间。
下边是timeWaitSetsockopt.c完整代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<errno.h>
#include<syslog.h>
#include<signal.h>

void error_handling(char *buf);

#define  MAXLINE     1024
static int count;
static void sig_int(int signo) {
    printf("\nreceived %d datagrams\n", count);
    exit(0);
}
int main(int argc, char **argv) {
    if (argc != 2) {
        error_handling("usage: select01 <IPaddress> or <Port>");
    }



    int serv_sock = socket(AF_INET,SOCK_STREAM,0);

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    server_addr.sin_port=htons(atoi(argv[1]));
    // SO_REUSEADDR用来告诉操作系统内核,如果端口已被占用,但是 TCP 连接状态位于 TIME_WAIT ,可以重用端口
    int on = 1;
    setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

    if(bind(serv_sock, (struct sockaddr*) &server_addr, sizeof(server_addr))==-1){
        fprintf(stderr, "error in bind: %s (%d)\n", strerror(errno), errno);
                    exit(errno);
    }
        if(listen(serv_sock, 5)==-1){
        fprintf(stderr, "error in listen: %s (%d)\n", strerror(errno), errno);
                    exit(errno);
    }


    signal(SIGPIPE, sig_int);


     int connfd;
    struct sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);

    if ((connfd = accept(serv_sock, (struct sockaddr *) &client_addr, &client_len)) < 0) {
        printf("accept failed");
        exit(0);
    }

    char message[MAXLINE];
    count = 0;
    int n;
    for (;;) {
        int n = read(connfd, message, MAXLINE);
        if (n < 0) {
            fprintf(stderr, "error in read: %s (%d)\n", strerror(errno), errno);
                    exit(0);
        } else if (n == 0) {
            fprintf(stderr, "client closed: %s (%d)\n", strerror(0), 0);
            exit(0);
        }
        message[n] = 0;
        printf("received %d bytes: %s\n", n, message);
        count++;
    }
}
void error_handling(char *buf)
{
        fputs(buf, stderr);
        fputc('\n', stderr);
        exit(1);
}

在服务器端sudo gcc timeWaitSetsockopt.c -o timeWaitSetsockopt进行编译,sudo ./timeWaitSetsockopt 8080启动程序。
在这里插入图片描述

在客户端使用sudo telnet 127.0.0.1 8080进行连接,然后输入good之后按下回车键。
在这里插入图片描述

然后在服务器端同时按住ctrl+c关闭程序,之后快速再使用sudo ./timeWaitSetsockopt 8080启动程序,然后快速在客户端使用sudo telnet 127.0.0.1 8080进行连接,输入network之后按下回车键,还是需要在服务器端快速按下sudo netstat -altnp | grep 8080看一下连接状态,这些动作只要够快就可以出现两条记录。
在这里插入图片描述


http://www.kler.cn/a/147144.html

相关文章:

  • 【C++滑动窗口】1248. 统计「优美子数组」|1623
  • 【MQTT.fx 客户端接入 阿里云平台信息配置】
  • uniapp微信小程序接入airkiss插件进行WIFI配网
  • stdin文件流指针
  • LlamaIndex+本地部署InternLM实践
  • Python知识点精汇!字符串:定义、截取(索引)和其内置函数
  • Pycharm在debug问题解决方案
  • 编译器设计01-入门概述
  • 力扣二叉树--第三十三天
  • nginx反向代理解决跨域前端实践
  • docker 安装jekins
  • 西南科技大学信号与系统A实验一(信号的产生与时域运算)
  • 微软Azure AI新增Phi、Jais等,40种新大模型
  • 对Laxcus分布式操作系统的认知、价值、痛点解决的回答
  • 第三节HarmonyOS DevEco Studio了解基本工程目录
  • JSP 循环ajax 返回的集合
  • 香港科技大学广州|智能制造学域博士招生宣讲会—天津大学专场
  • Apache换行解析漏洞(CVE-2017-15715)
  • 红米手机如何远程控制荣耀手机?
  • 在OpenCV中基于深度学习的边缘检测
  • nuxt、vue实现PDF和视频文件的上传、下载、预览
  • go语言基础 break和contine区别
  • Mac 搭建本地服务器
  • 云原生系列Go语言篇-泛型Part 1
  • 2-Python与设计模式--前言
  • MIT6.824-Raft笔记:Raft初探、副本间log时序