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. MTK Android Driver :Battery电池曲线

    MTK Android Driver :battery电池曲线 1.配置文件位置: CUSTOM_KERNEL_BATTERY= battery mediatek\custom\\kernel\bat ...

  2. Java第八天,抽象的概念是什么?如何完成抽象类的实现?

    抽象 面向对象编程中,抽象是一个很重要的概念,那么抽象有什么需要注意的地方呢?请熟记以下知识点. 如果父类当中的方法不确定如何进行方法体的实现,则这个方法就是抽象方法. 抽象方法只需要在方法前面加上a ...

  3. Java第三天,如何从键盘输入?匿名对象的使用方法

    在学习完Java的基础语法之后,我们还需要学会如何使用API文档,这几乎是程序员所必备的能力.对于API我们不必须去记住每一个类的功能乃至用法,只需会查就行了.但是话说回来,一些经常使用的类我们还是必 ...

  4. Array(数组)对象-->sort() 方法

    1.定义和用法 sort() 方法用于对数组的元素进行排序. 默认排序顺序为按字母升序. 语法: array.sort(sortfunction) 参数: sortfunction:规定排序顺序.必须 ...

  5. "字母全变大写"组件:<uppercase> —— 快应用组件库H-UI

     <import name="uppercase" src="../Common/ui/h-ui/text/c_text_uppercase">& ...

  6. Web开发与设计之Google兵器谱-Web开发与设计利器

    Web开发与设计之Google兵器谱-Web开发与设计利器 博客分类: Java综合 WebGoogleAjaxChromeGWT 笔者是个Java爱好者也是用Java进行web开发的工作者.平时笔者 ...

  7. PHP代码审计(初级篇)

    一.常见的PHP框架 1.zendframwork: (ZF)是Zend公司推出的一套PHP开发框架 功能非常的强大,是一个重量级的框架,ZF 用 100%面向对象编码实现. ZF 的组件结构独一无二 ...

  8. E - Dungeon Master BFS

    [NWUACM] 你被困在一个三维的空间中,现在要寻找最短路径逃生!空间由立方体单位构成你每次向上下前后左右移动一个单位需要一分钟你不能对角线移动并且四周封闭是否存在逃出生天的可能性?如果存在,则需要 ...

  9. ExceptionInChainedOperatorException:flink写hbase对于null数据导致数据导致出现异常

    使用的flink版本:1.9.1 异常描述 需求: 从kafka读取一条数据流 经过filter初次筛选符合要求的数据 然后通过map进行一次条件判断再解析.这个这个过程中可能返回null或目标输出o ...

  10. Postman:Pre-request Script

    Pre-request Script:前置处理,会在发出请求前执行,主要用在生成一些动态参数. 例如:api接口都会有签名校验,这个校验在我们api测试的时候很不方便,这里可以利用 postman 前 ...