Socket中SO_REUSEADDR简介
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.一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用. SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的sock ...
- linux socket中的SO_REUSEADDR
Welcome to the wonderful world of portability... or rather the lack of it. Before we start analyzing ...
- Socket通信原理简介
Socket通信原理简介 字数1011 阅读1766 评论2 喜欢11 何谓socket 计算机,顾名思义即是用来做计算.因而也需要输入和输出,输入需要计算的条件,输出计算结果.这些输入输出可以抽象为 ...
- 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_ ...
- Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)
声明:该博文以socket中,关闭输出流为例进行说明. 为了方便讲解,我们把DataOutputstream dout = new DataOutputStream(new BufferedOutpu ...
- 2、 Spark Streaming方式从socket中获取数据进行简单单词统计
Spark 1.5.2 Spark Streaming 学习笔记和编程练习 Overview 概述 Spark Streaming is an extension of the core Spark ...
- Spring中AOP简介与切面编程的使用
Spring中AOP简介与使用 什么是AOP? Aspect Oriented Programming(AOP),多译作 "面向切面编程",也就是说,对一段程序,从侧面插入,进行操 ...
- Socket中常见的几个转换函数(htonl,htons,ntohl,ntohs,inet_addr,inet_ntoa)
Socket中常见的几个转换函数(htonl,htons,ntohl,ntohs,inet_addr,inet_ntoa) htonl() htons() ntohl() ntohs()及inet_n ...
- ioctl在socket中的一些用法及示例
原文: http://blog.chinaunix.net/uid-20692625-id-3172833.html ----------------------------------------- ...
随机推荐
- MTK Android Driver :Camera
MTK Android Driver :camera 1.相关代码位置:mediatek\config\XXXX(红色字为具体的项目名) 文件:ProjectConfig.mk CUSTOM_KERN ...
- lr集合点
集合点:rendezvous point =====>>loadrunner的虚拟用户中,并发concurrent\ 同时simultaneous的区别: concurrent并发:指虚拟 ...
- 1.Git 安装
Git的安装 阿里云镜像去下载 阿里云的镜像地址 卸载Git 1.首先在系统环境变量->path->里面去清理掉git相关的环境变量 2.然后控制面板卸载 安装Git 一直下一步即可 使用 ...
- 使用d3.js的时候,如何用zoom translate scale限制拖拽范围
红色代表需要改写的代码 1.添加定义图像大小和容器的大小及坐标 d3.behavior.zoom = function () { var moveCanvas={ width: , height: , ...
- PDF各种骚操作如何用python实现
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: wLsq PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...
- 极验反爬虫防护分析之slide验证方式下图片的处理及滑动轨迹的生成思路
本文要分享的内容是去年为了抢鞋而分析 极验(GeeTest)反爬虫防护的笔记,由于篇幅较长(为了多混点CB)我会按照我的分析顺序,分成如下四个主题与大家分享: 极验反爬虫防护分析之交互流程分析 极验反 ...
- 5. class--extends
ES5: function article(x,y){ this.x = x; this.y = y; } article.prototype.say = function() { return (t ...
- Spring5:面向切面
静态代理 缺点:一个真实角色就会产生一个代理角色,代码量会翻倍! 场景:要在写好的实现方法上加入日志功能(公共功能),不要修改原代码 1:原代码 业务接口: package com.spring; p ...
- AOP-SheepAspect
转载https://www.cnblogs.com/InCsharp/p/5902133.html SheepAspect 简介以及代码示列: SheepAspect是一个AOP框架为.NET平台,深 ...
- Jquery中 $.Ajax() 参数详解
1.url:要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type:要求为String类型的参数,请求方式(post或get)默认为get.注意其他http请求方法,例如pu ...