精华内容
下载资源
问答
  • SO_REUSEADDR

    2021-07-31 10:25:41
    SO_REUSEADDR 一个网络应用程序只能绑定一个端口( 一个套接字只能绑定一个端口 )。 实际上,默认的情况下,如果一个网络应用程序的一个套接字 绑定了一个端口( 占用了 8000 ),这时候,别的套接字就无法使用这个端口...

    SO_REUSEADDR

    一个网络应用程序只能绑定一个端口( 一个套接字只能绑定一个端口 )。

    实际上,默认的情况下,如果一个网络应用程序的一个套接字 绑定了一个端口( 占用了 8000 ),这时候,别的套接字就无法使用这个端口( 8000 ), 验证例子如下:

    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <unistd.h>
    
    int main(int argc, char* argv[])
    {
        int sockfd_one;
        int err_log;
        sockfd_one = socket(AF_INET, SOCK_DGRAM, 0); //创建UDP套接字one
        if (sockfd_one < 0) {
            perror("sockfd_one");
            exit(-1);
        }
    
        // 设置本地网络信息
        struct sockaddr_in my_addr;
        bzero(&my_addr, sizeof(my_addr));
        my_addr.sin_family = AF_INET;
        my_addr.sin_port = htons(8000); // 端口为8000
        my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
        // 绑定,端口为8000
        err_log = bind(sockfd_one, (struct sockaddr*)&my_addr, sizeof(my_addr));
        if (err_log != 0) {
            perror("bind sockfd_one");
            close(sockfd_one);
            exit(-1);
        }
    
        int sockfd_two;
        sockfd_two = socket(AF_INET, SOCK_DGRAM, 0); //创建UDP套接字two
        if (sockfd_two < 0) {
            perror("sockfd_two");
            exit(-1);
        }
    
        // 新套接字sockfd_two,继续绑定8000端口,绑定失败
        // 因为8000端口已被占用,默认情况下,端口没有释放,无法绑定
        err_log = bind(sockfd_two, (struct sockaddr*)&my_addr, sizeof(my_addr));
        if (err_log != 0) {
            perror("bind sockfd_two");
            close(sockfd_two);
            exit(-1);
        }
    
        close(sockfd_one);
        close(sockfd_two);
    
        return 0;
    }
    
    m@ubuntu:~/test$ gcc 1.c
    m@ubuntu:~/test$ ./a.out 
    bind sockfd_two: Address already in use
    

    那如何让sockfd_one, sockfd_two两个套接字都能成功绑定8000端口呢?这时候就需要要到端口复用了。端口复用允许在一个应用程序可以把 n 个套接字绑在一个端口上而不出错。

    设置socket的SO_REUSEADDR选项,即可实现端口复用:

    int opt = 1;
    // sockfd为需要端口复用的套接字
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));
    

    SO_REUSEADDR可以用在以下四种情况下。 (摘自《Unix网络编程》卷一,即UNPv1)

    1、当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。

    2、SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可以测试这种情况。

    3、SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。这和2很相似,区别请看UNPv1。

    4、SO_REUSEADDR允许完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。

    需要注意的是,设置端口复用函数要在绑定之前调用,而且只要绑定到同一个端口的所有套接字都得设置复用:

    // sockfd_one, sockfd_two都要设置端口复用
    // 在sockfd_one绑定bind之前,设置其端口复用
    int opt = 1;
    setsockopt( sockfd_one, SOL_SOCKET,SO_REUSEADDR, (const void *)&opt, sizeof(opt) );
    err_log = bind(sockfd_one, (struct sockaddr*)&my_addr, sizeof(my_addr));
     
    // 在sockfd_two绑定bind之前,设置其端口复用
    opt = 1;
    setsockopt( sockfd_two, SOL_SOCKET,SO_REUSEADDR,(const void *)&opt, sizeof(opt) );
    err_log = bind(sockfd_two, (struct sockaddr*)&my_addr, sizeof(my_addr));
    

    端口复用的完整代码如下

    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <unistd.h>
    
    int main(int argc, char* argv[])
    {
        int sockfd_one;
        int err_log;
        sockfd_one = socket(AF_INET, SOCK_DGRAM, 0); //创建UDP套接字one
        if (sockfd_one < 0) {
            perror("sockfd_one");
            exit(-1);
        }
    
        // 设置本地网络信息
        struct sockaddr_in my_addr;
        bzero(&my_addr, sizeof(my_addr));
        my_addr.sin_family = AF_INET;
        my_addr.sin_port = htons(8000); // 端口为8000
        my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
        // 在sockfd_one绑定bind之前,设置其端口复用
        int opt = 1;
        setsockopt(sockfd_one, SOL_SOCKET, SO_REUSEADDR,
            (const void*)&opt, sizeof(opt));
    
        // 绑定,端口为8000
        err_log = bind(sockfd_one, (struct sockaddr*)&my_addr, sizeof(my_addr));
        if (err_log != 0) {
            perror("bind sockfd_one");
            close(sockfd_one);
            exit(-1);
        }
    
        int sockfd_two;
        sockfd_two = socket(AF_INET, SOCK_DGRAM, 0); //创建UDP套接字two
        if (sockfd_two < 0) {
            perror("sockfd_two");
            exit(-1);
        }
    
        // 在sockfd_two绑定bind之前,设置其端口复用
        opt = 1;
        setsockopt(sockfd_two, SOL_SOCKET, SO_REUSEADDR,
            (const void*)&opt, sizeof(opt));
    
        // 新套接字sockfd_two,继续绑定8000端口,成功
        err_log = bind(sockfd_two, (struct sockaddr*)&my_addr, sizeof(my_addr));
        if (err_log != 0) {
            perror("bind sockfd_two");
            close(sockfd_two);
            exit(-1);
        }
    
        close(sockfd_one);
        close(sockfd_two);
    
        return 0;
    }
    

    端口复用允许在一个应用程序可以把 n 个套接字绑在一个端口上而不出错。同时,这 n 个套接字发送信息都正常,没有问题。但是,这些套接字并不是所有都能读取信息,只有最后一个套接字会正常接收数据。其实相当于把接管了。

    下面,我们在之前的代码上,添加两个线程,分别负责接收sockfd_one,sockfd_two的信息:

    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <unistd.h>
    
    // 线程1的回调函数
    void* recv_one(void* arg)
    {
        printf("===========recv_one==============\n");
        int sockfd = (int)arg;
        while (1) {
            int recv_len;
            char recv_buf[512] = "";
            struct sockaddr_in client_addr;
            char cli_ip[INET_ADDRSTRLEN] = ""; //INET_ADDRSTRLEN=16
            socklen_t cliaddr_len = sizeof(client_addr);
    
            recv_len = recvfrom(sockfd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr*)&client_addr, &cliaddr_len);
            inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);
            printf("\nip:%s ,port:%d\n", cli_ip, ntohs(client_addr.sin_port));
            printf("sockfd_one =========== data(%d):%s\n", recv_len, recv_buf);
        }
    
        return NULL;
    }
    
    // 线程2的回调函数
    void* recv_two(void* arg)
    {
        printf("+++++++++recv_two++++++++++++++\n");
        int sockfd = (int)arg;
        while (1) {
            int recv_len;
            char recv_buf[512] = "";
            struct sockaddr_in client_addr;
            char cli_ip[INET_ADDRSTRLEN] = ""; //INET_ADDRSTRLEN=16
            socklen_t cliaddr_len = sizeof(client_addr);
    
            recv_len = recvfrom(sockfd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr*)&client_addr, &cliaddr_len);
            inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);
            printf("\nip:%s ,port:%d\n", cli_ip, ntohs(client_addr.sin_port));
            printf("sockfd_two @@@@@@@@@@@@@@@ data(%d):%s\n", recv_len, recv_buf);
        }
    
        return NULL;
    }
    
    int main(int argc, char* argv[])
    {
        int err_log;
    
        int sockfd_one;
        sockfd_one = socket(AF_INET, SOCK_DGRAM, 0); //创建UDP套接字one
        if (sockfd_one < 0) {
            perror("sockfd_one");
            exit(-1);
        }
    
        // 设置本地网络信息
        struct sockaddr_in my_addr;
        bzero(&my_addr, sizeof(my_addr));
        my_addr.sin_family = AF_INET;
        my_addr.sin_port = htons(8000); // 端口为8000
        my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
        // 在sockfd_one绑定bind之前,设置其端口复用
        int opt = 1;
        setsockopt(sockfd_one, SOL_SOCKET, SO_REUSEADDR,
            (const void*)&opt, sizeof(opt));
    
        // 绑定,端口为8000
        err_log = bind(sockfd_one, (struct sockaddr*)&my_addr, sizeof(my_addr));
        if (err_log != 0) {
            perror("bind sockfd_one");
            close(sockfd_one);
            exit(-1);
        }
    
        //接收信息线程1
        pthread_t tid_one;
        pthread_create(&tid_one, NULL, recv_one, (void*)sockfd_one);
    
        int sockfd_two;
        sockfd_two = socket(AF_INET, SOCK_DGRAM, 0); //创建UDP套接字two
        if (sockfd_two < 0) {
            perror("sockfd_two");
            exit(-1);
        }
    
        // 在sockfd_two绑定bind之前,设置其端口复用
        opt = 1;
        setsockopt(sockfd_two, SOL_SOCKET, SO_REUSEADDR,
            (const void*)&opt, sizeof(opt));
    
        // 新套接字sockfd_two,继续绑定8000端口,成功
        err_log = bind(sockfd_two, (struct sockaddr*)&my_addr, sizeof(my_addr));
        if (err_log != 0) {
            perror("bind sockfd_two");
            close(sockfd_two);
            exit(-1);
        }
        //接收信息线程2
        pthread_t tid_two;
        pthread_create(&tid_two, NULL, recv_two, (void*)sockfd_two);
    
        while (1) { // 让程序阻塞在这,不结束
            NULL;
        }
    
        close(sockfd_one);
        close(sockfd_two);
    
        return 0;
    }
    

    接着,通过客户端给这个服务器发送数据,结果显示,只有最后一个套接字sockfd_two会正常接收数据:

    m@ubuntu:~/test$ gcc 1.c -lpthread                                              ^
    m@ubuntu:~/test$ ./a.out 
    ===========recv_one==============
    +++++++++recv_two++++++++++++++
    
    ip:127.0.0.1 ,port:36348
    sockfd_two @@@@@@@@@@@@@@@ data(4):222
    
    
    ip:127.0.0.1 ,port:47277
    sockfd_two @@@@@@@@@@@@@@@ data(11):3333333333
    

    另一个终端编译并运行如下程序

    /*
     * mx
     */
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<sys/socket.h>
    #include<netinet/in.h>
    const int SERV_PORT=8000;
    const int MAXLINE=2048;
    
    void dg_cli(FILE* fp,int sockfd,const struct sockaddr* pservaddr,socklen_t servlen)
    {
        int n;
        char sendline[MAXLINE],recvline[MAXLINE+1];
        while(fgets(sendline,MAXLINE,fp)!=NULL)
        {
            if(sendto(sockfd,sendline,strlen(sendline),0,pservaddr,servlen)<0)
            {
                perror("sendto error");
                exit(1);
            }
            if((n=recvfrom(sockfd,recvline,MAXLINE,0,NULL,NULL))<0)
            {
                perror("recvfrom error");
                exit(1);
            }
            recvline[n]='\0';
            fputs(recvline,stdout);
        }
    }
    
    int main(int argc,char** argv)
    {
        int sockfd,t;
        struct sockaddr_in servaddr;
        if(argc!=2)
        {
            perror("usage: udpcli<IPaddress>");
            exit(1);
        }
        bzero(&servaddr,sizeof(servaddr));
        servaddr.sin_family=AF_INET;
        servaddr.sin_port=htons(SERV_PORT);
        if((t=inet_pton(AF_INET,argv[1],&servaddr.sin_addr))<=0)
        {
            perror("inet_pton error");
            exit(1);
        }
        if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0)
        {
            perror("socket error");
            exit(1);
        }
        dg_cli(stdin,sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
        exit(0);
    }
    
    m@ubuntu:~/test$ gcc 2.c
    m@ubuntu:~/test$ ./a.out 127.0.0.1
    222
    ^C
    m@ubuntu:~/test$ ./a.out 127.0.0.1
    3333333333
    

    我们上面的用法,实际上没有太大的意义。端口复用最常用的用途应该是防止服务器重启时之前绑定的端口还未释放或者程序突然退出而系统没有释放端口。这种情况下如果设定了端口复用,则新启动的服务器进程可以直接绑定端口。如果没有设定端口复用,绑定会失败,提示ADDR已经在使用中——那只好等等再重试了,麻烦!

    展开全文
  • SO_REUSEADDR使用

    2021-04-21 22:20:54
    SO_REUSEADDR是一个很有用的选项,一般服务器的监听socket都应该打开它。它的大意是允许服务器bind一个地址,即使这个地址当前已经存在已建立的连接,比如: 服务器启动后,有客户端连接并已建立,如果服务器主动...

    SO_REUSEADDR是一个很有用的选项,一般服务器的监听socket都应该打开它。它的大意是允许服务器bind一个地址,即使这个地址当前已经存在已建立的连接,比如:

    • 服务器启动后,有客户端连接并已建立,如果服务器主动关闭,那么和客户端的连接会处于TIME_WAIT状态,此时再次启动服务器,就会bind不成功,报:Address already in use。
    • 服务器父进程监听客户端,当和客户端建立链接后,fork一个子进程专门处理客户端的请求,如果父进程停止,因为子进程还和客户端有连接,所以再次启动父进程,也会报Address already in use。
    展开全文
  • SO_REUSEADDR用法

    2017-08-11 14:08:31
    1、一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用。SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的socket,才可以重复绑定使用。server程序总是应该...

    1、一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用。

    SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的socket,才可以重复绑定使用。server程序总是应该在调用bind()之前设置SO_REUSEADDR套接字选项。TCP,先调用close()的一方会进入TIME_WAIT状态。
    

    SO_REUSEADDR提供如下四个功能:

    SO_REUSEADDR允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将此端口用做他们的本地端口的连接仍存在。这通常是重启监听服务器时出现,若不设置此选项,则bind时将出错。
    
    SO_REUSEADDR允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址即可。对于TCP,我们根本不可能启动捆绑相同IP地址和相同端口号的多个服务器。
    
    SO_REUSEADDR允许单个进程捆绑同一端口到多个套接口上,只要每个捆绑指定不同的本地IP地址即可。这一般不用于TCP服务器。
    
    SO_REUSEADDR允许完全重复的捆绑:当一个IP地址和端口绑定到某个套接口上时,还允许此IP地址和端口捆绑到另一个套接口上。一般来说,这个特性仅在支持多播的系统上才有,而且只对UDP套接口而言(TCP不支持多播)。
    

    SO_REUSEPORT选项有如下语义:

    此选项允许完全重复捆绑,但仅在想捆绑相同IP地址和端口的套接口都指定了此套接口选项才行。
    
    如果被捆绑的IP地址是一个多播地址,则SO_REUSEADDR和SO_REUSEPORT等效。
    

    使用这两个套接口选项的建议:

    在所有TCP服务器中,在调用bind之前设置SO_REUSEADDR套接口选项;
    

    当编写一个同一时刻在同一主机上可运行多次的多播应用程序时,设置SO_REUSEADDR选项,并将本组的多播地址作为本地IP地址捆绑。

    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
    
    (const void *)&nOptval , sizeof(int)) < 0) ...
    

    Q:编写 TCP/SOCK_STREAM 服务程序时,SO_REUSEADDR到底什么意思?
    
    A:这个套接字选项通知内核,如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用端口。如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息,指明"地址已经使用中"。如果你的服务程序停止后想立即重启,而新套接字依旧使用同一端口,此时SO_REUSEADDR 选项非常有用。必须意识到,此时任何非期望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不可能。
    
    一个套接字由相关五元组构成,协议、本地地址、本地端口、远程地址、远程端口。SO_REUSEADDR 仅仅表示可以重用本地本地地址、本地端口,整个相关五元组还是唯一确定的。所以,重启后的服务程序有可能收到非期望数据。必须慎重使用SO_REUSEADDR 选项。
    
    展开全文
  • SO_REUSEADDR & SO_REUSEPORT

    2020-01-07 18:37:52
    SO_REUSEADDR 当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。 SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)...

    SO_REUSEADDR

    1. 当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。
    2. SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可
      以测试这种情况。
    3. SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。这和2很相似,区别请看UNPv1。
    4. SO_REUSEADDR允许完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。

    SO_REUSEPORT

    The new socket option allows multiple sockets on the same host to bind to the same port, and is intended to improve the performance of multithreaded network server applications running on top of multicore systems.

    linux kernel 3.9引入了最新的SO_REUSEPORT选项,使得多进程或者多线程可以创建多个绑定同一个ip:port的监听socket,提高服务器的接收连接的并发能力,程序的扩展性更好;此时需要设置SO_REUSEPORT(注意所有进程都要设置才生效)。

    目的:每一个进程有一个独立的监听socket,并且bind相同的ip:port,独立的listen()和accept();提高接收连接的能力。(例如nginx多进程同时监听同一个ip:port)

    解决的问题:

    • 避免了应用层多线程或者进程监听同一ip:port的“惊群效应”。
    • 内核层面实现负载均衡,保证每个进程或者线程接收均衡的连接数。
    • 只有effective-user-id相同的服务器进程才能监听同一ip:port (安全性考虑)

    golang开源实现:https://github.com/kavu/go_reuseport

    注意:SO_REUSEPORT只支持TCP和UDP。对unix domain socket不生效。

    展开全文
  • SO_REUSEADDR解释

    2017-06-02 09:40:07
    一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用。 SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的socket,才可以重复绑定使用。server程序总是应该...
  • 下面小编就为大家分享一篇详谈套接字中SO_REUSEPORT和SO_REUSEADDR的区别,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • gsoap SO_REUSEADDR

    2017-11-07 16:48:49
    在用gsoap时碰到一个问题,就是当把程序建立连接后停止立即再启动就会报“Address already in use”错误,过一会再启动就没问题了。...socket中这么设置 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
  • Socket中SO_REUSEADDR详解

    万次阅读 多人点赞 2017-11-20 10:05:24
    1、一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用。 SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的socket,才可以重复绑定使用。server程序总是应该...
  • SO_REUSEADDR提供如下四个功能: SO_REUSEADDR允许启动一个监听服务器并捆绑一个端口,即使以前建立的将此端口用做他们的本地端口的连接仍存在(TIME_WAIT)。这通常是重启监听服务器时出现,若不设置此选项,则bind...
  • SO_REUSEADDR说明

    2015-08-19 14:20:15
    1、一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用。  SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的socket,才可以重复绑定使用。server程序...
  • Time-wait SO_REUSEADDR

    2018-12-13 21:39:43
    哪端首先 close(socket) -&gt; FIN 传递后. 经过4次握手后即进入 time-wait  time-wait 会等待一段时间....对于服务器来说, 可使用 SO_REUSEADDR  int sockfd = socket(PF_INET,SOCK_STREAM,0); in...
  • 实战测试SO_REUSEADDR选项

    万次阅读 2017-10-01 11:19:39
    设置SO_REUSEADDR选项,对应TCP套接字处于TIME_WAIT状态下的socket可以重复绑定实用,看代码吧。 服务端: #include #include #include #include #include #include #include #include #include #include ...
  • TCP选项分析 之 SO_REUSEADDR 首先 从工程角度考虑如下问题 问题: 1:Server 进行 bind(),listen(),accept(),然后进行等待Client连接。 2:Client 进行 连接。即,Server的accept()返回client_fd 3:Server...
  • TCP选项之SO_REUSEADDR

    2018-08-01 15:08:29
    1、一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用。  SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的socket,才可以重复绑定使用。server程序总是...
  • SO_REUSEADDR 开启场景 多网卡(IP)绑定相同端口; 让关闭连接释放的端口今早可使用; TCP 四次挥手 TCP 四次挥手.png TIME-WAIT 的作用一:作为 ACK 的容错时间 Client 最后的 ACK 不一定能成功到达 ...
  • SO_REUSEADDR套接字选项

    2017-04-16 13:26:14
    SO_REUSEADDR 选项
  • socket SO_REUSEADDR

    2014-03-29 20:46:18
    SO_REUSEADDR可以用在以下四种情况下。  (摘自《Unix网络编程》卷一,即UNPv1)  1、当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启 动的程序的socket2要占用该地址和端口,你的程序就要...
  • SO_REUSEADDR/SO_REUSEPORT到底什么意思? 设置SO_REUSEADDR选项 TIME_WAIT有什么意义呢? SO_REUSEADDR/SO_REUSEPORT到底什么意思? SO_REUSEADDR选项有如下语义: 这个套接字选项通知内核,如果端口忙,但TCP...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 27,088
精华内容 10,835
关键字:

reuseaddr