SO_REUSEADDR:字面意思重复使用地址

一般来说,一个端口释放后会等待两分钟之后才能再次被使用,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_REUSEADDR的建议:

1. 在所有TCP服务器中,在调用bind之前设置SO_REUSEADDR套接口选项(不一定,一般在调试阶段)

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

问题场景

当在开发一个socket服务器程序并反复调试的时候,可能会发现这样一种情况。每次kill掉该服务器进程并重新启动的时候,都会出现bind错误:error:98,Address already in use。然后再kill掉该进程,再次重新启动的时候,就bind成功了

这实际上是TIME_WAIT在起作用!linux的TIME_WAIT大概是2分钟,在调试的时候需要等2分钟?

解决问题

一般是没有办法关闭掉TIME_WAIT,可以使用SO_REUSEADDR,允许端口在释放后被立即使用。

// 设置允许地址重用
int on = ;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

上面两行代码,在套接字listenfd设置允许地址重用(on = 1,如果on = 0就是不允许重用)。这样每次bind的时候,如果此端口正在使用的话,bind就会把端口"抢"过来,就不会报错了。

TIME_WAIT存在的理由:

(1)可靠的实现TCP全双工连接的终止

(2)允许老的重复分节在网络中消逝

解释如下:

(1)如果服务器最后发送的ACK因为某种原因丢失了,那么客户一定会重新发送FIN,这样因为有了TIME_WAIT的存在,服务器会重新发送ACK给客户,如果没有TIME_WAIT,那么无论客户有没有收到ACK,服务器都已经关掉连接了,此时客户重新发送FIN,服务器将不会发送ACK,而是RST,从而使客户端报错。也就是说,TIME_WAIT有助于可靠地实现TCP全双工连接的终止。

(2)如果没有TIME_WAIT,我们可以在最后一个ACK还未到客户的时候,就建立一个新的连接。那么此时,如果客户收到了这个ACK的话,会出现混乱,必须保证这个ACK完全消逝之后,才能建立新的连接。也就是说,TIME_WAIT允许老的重复分节在网络中消逝。

建议:在最终的服务器版本,还是不要设置为端口可复用。

参考链接:Socket中SO_REUSEADDR详解

 

Socket中SO_REUSEADDR简介的更多相关文章

  1. Socket中SO_REUSEADDR详解

    1.一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用. SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的sock ...

  2. linux socket中的SO_REUSEADDR

    Welcome to the wonderful world of portability... or rather the lack of it. Before we start analyzing ...

  3. Socket通信原理简介

    Socket通信原理简介 字数1011 阅读1766 评论2 喜欢11 何谓socket 计算机,顾名思义即是用来做计算.因而也需要输入和输出,输入需要计算的条件,输出计算结果.这些输入输出可以抽象为 ...

  4. ZeroMQ接口函数之 :zmq_msg_recv - 从一个socket中接受一个消息帧

    ZeroMQ 官方地址 :http://api.zeromq.org/4-2:zmq_msg_recv zmq_msg_recv(3) ØMQ Manual - ØMQ/3.2.5 Name zmq_ ...

  5. Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)

    声明:该博文以socket中,关闭输出流为例进行说明. 为了方便讲解,我们把DataOutputstream dout = new DataOutputStream(new BufferedOutpu ...

  6. 2、 Spark Streaming方式从socket中获取数据进行简单单词统计

    Spark 1.5.2 Spark Streaming 学习笔记和编程练习 Overview 概述 Spark Streaming is an extension of the core Spark ...

  7. Spring中AOP简介与切面编程的使用

    Spring中AOP简介与使用 什么是AOP? Aspect Oriented Programming(AOP),多译作 "面向切面编程",也就是说,对一段程序,从侧面插入,进行操 ...

  8. Socket中常见的几个转换函数(htonl,htons,ntohl,ntohs,inet_addr,inet_ntoa)

    Socket中常见的几个转换函数(htonl,htons,ntohl,ntohs,inet_addr,inet_ntoa) htonl() htons() ntohl() ntohs()及inet_n ...

  9. ioctl在socket中的一些用法及示例

    原文: http://blog.chinaunix.net/uid-20692625-id-3172833.html ----------------------------------------- ...

随机推荐

  1. Python 1基础语法二(标识符、关键字、变量和字符串)

    一.标识符 标识符就是程序员自己命名的变量名.名字需要有见名知义的效果,不要随意起名 :比如 a=1 a是个变量,a这个变量名属于标识符 1 company = '小米 2 employeeNum = ...

  2. CH5105 Cookies (线性dp)

    传送门 解题思路: 贪心的想,贪婪值越大的孩子应该分得更多的饼干,那么先sort一遍在此基础上进行dp.最直观的方向,可以设dp[i][j]为前i个孩子一共分得j块饼干的怨恨最小值.然后转移第i+1个 ...

  3. 教你爬取腾讯课堂、网易云课堂、mooc等所有课程信息

    本文的所有代码都在GitHub上托管,想要代码的同学请点击这里

  4. git如何清除远程 __pycahce__ 文件

    第一步,清除已经存在的缓存文件 >> git rm -r -f --cached */__pycache__ rm 'common/__pycache__/__init__.cpython ...

  5. Python 文件拼接

    # -*- coding:utf-8 -*- import re import csv file = open('make_setup.cfg', 'w+') with open("tyb. ...

  6. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(三)之Everything Is an Object

    ---恢复内容开始--- Both C++ and Java are hybird languages. A hybird language allow multiple programming st ...

  7. python3-邮件发送-不同格式

    0x00 邮件格式 要发邮件,总要先了解邮件格式吧,这里指的是邮件的各个部分与python中SMTP所对应的一些必须的格式 0x01 简单发送邮件格式如下: import smtplib from e ...

  8. code-breaking picklecode中对signed_cookies引擎分析

    最近做了 ph 牛的 code-breaking,在做 picklecode 这一题时,没有搞懂那个 django 的 signed_cookies 引擎对 session 的操作,就 debug 了 ...

  9. C++头文件问题

    自己定义的头文件必须要用“***.h”系统头文件必须要用<***.h>stdafx.h 必须放在所有头文件的最前面(如果不放,debug版本没有问题:release版本有问题,会报错)

  10. Docker 搭建 ELK 集群步骤

    前言 本篇文章主要介绍在两台机器上使用 Docker 搭建 ELK. 正文 环境 CentOS 7.7 系统 Docker version 19.03.8 docker-compose version ...