java socket-Socket端口复用(setReuseAddress)
发布日期:2021-06-29 22:24:21 浏览次数:2 分类:技术文章

本文共 1676 字,大约阅读时间需要 5 分钟。

socket.setReuseAddress(true); 含义

设置Socket的选项

参考URL: https://blog.csdn.net/qq_34444097/article/details/78966654

如下代码, sock.setReuseAddress(true);什么含义?

public static Socket getSocket(InetSocketAddress addr) throws IOException {
Socket sock = new Socket(); sock.setReuseAddress(true); sock.setSoTimeout(ClientGlobal.g_network_timeout); sock.connect(addr, ClientGlobal.g_connect_timeout); return sock; }

在网络应用中(如Java Socket Server),当服务关掉立马重启时,很多时候会提示端口仍被占用(因端口上有处于TIME_WAIT的连接)。此时可通过 SO_REUSEADDR 参数( socket.setReuseAddress(true); )来使得服务关掉重启时立马可使用该端口,而不是提示端口占用。

如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用 端口。如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息, 抛出“Address already in use: JVM_Bind”。如果你的服务程序停止后想立即重启,不等60秒,而新套接字依旧 使用同一端口,此时 SO_REUSEADDR 选项非常有用。

TCP关闭过程中的TIME_WAIT状态就是client端的2MSL状态,其作用是确保server端可以收到client端发送的确认报文:最后一个确认报文可能没被server端收到,此时server端会重发fin报文,client端等待2MSL时间使得可以收到server端重发的fin报文。

SO_RESUSEADDR选项:

  • 设置该选项:public void setResuseAddress(boolean on)throws SocketException
  • 读取该选项 public void getResuseAddress(boolean on)throws SocketException

当接受方通过Socket的close()方法关闭Socket时,如果网络上还有发送到这个Socket的数据,那么底层的Socket不会立刻释放本地端口,而是会等待一段时间,确保收到了网络上发送过来的延迟数据,然再释放该端口。Socket接受到延迟数据后,不会对这些数据做任何处理。Socket接受延迟数据的目的是,确保这些数据不会被其他碰巧绑定到同样端口的新进程接收到。

客户程序一般采用随机端口,因此会出现两个客户端程序绑定到同样端口的可能性不大。许多服务器都使用固定的端口。当服务器进程关闭后,有可能它的端口还会被占用一段时间,如果此时立刻在同一主机上重启服务器程序,由于端口已经被占用,使得服务器无法绑定到该端口,启动失败。为了确保一个进程被关闭后,及时它还没有释放该端口,同一个主机上的其他进程还可以立刻重用该端口,可以调用Socket的setResuseAddress(true)方法:

值得注意的是:socket.setResuseAddress(true)方法必须在Socket还没有绑定到一个本地端口之前调用,否则执行socket.setResuseAddress(true)方法无效

因此必须按照以下方法创建Socket对象,然后在连接远程服务器:

此外,两个共用同一个端口的进程必须都调用socket.setReuseAddress(true)放方法才能使得一个进程关闭Socket后,另一个进程的Socket能够立刻重用相同的端口。

转载地址:https://docker.blog.csdn.net/article/details/106158128 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:fastdfs-获取文件信息源码分析(文件类型判断)
下一篇:git-移除某文件或文件夹的版本控制(ignore)

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年04月19日 19时41分36秒