java Socket的选项

本文详细介绍了SO_REUSEADDR选项的作用及使用方法,解释了如何在Java中通过ServerSocket类设置和获取该选项,以实现同一端口的重复绑定,并探讨了在实际应用中的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SO_REUSEADDR选项决定了一个端口是否可以被绑定多次。可以通过SeverSocket类的两个方法(setReuseAddres和getReuseAddress)来设置和获得SO_TIMEOUT选项的值,这两个方法的定义如下:

public void setReuseAddress(boolean on) throws SocketException 
public boolean getReuseAddress() throws SocketException

在大多数操作系统中都不允许一个端口被多次绑定。如果一个ServerSocket对象绑定了已经被占用的端口,那么ServerSocket的构造方法或bind方法就会抛出一个BindException异常。

Java提供这个选项的主要目的是为了防止由于频繁绑定释放一个固定端口而使系统无法正常工作。当ServerSocket对象关闭后,如果ServerSocket对象中仍然有未处理的数据,那么它所绑定的端口可能在一段时间内不会被释放。这就会造成其他的ServerSocket对象无法绑定这个端口。在设置这个选项时,如果某个端口是第一次被绑定,无需调用setReuseAddress方法,而再次绑定这个端口时,必须使用setReuseAddress方法将这个选项设为true。而且这个方法必须在调用bind方法之前调用。下面的代码演示了如何设置和获得这个选项的值:

package server;
import java.net.*;
public class TestReuseAddr1
{
     public static void main(String[] args) throws Exception
     {
         ServerSocket serverSocket1 = new ServerSocket(1234);
         System.out.println(serverSocket1.getReuseAddress());

         ServerSocket serverSocket2 = new ServerSocket();
         serverSocket2.setReuseAddress(true);
         serverSocket2.bind(new InetSocketAddress(1234));

         ServerSocket serverSocket3 = new ServerSocket();
         serverSocket3.setReuseAddress(true);
         serverSocket3.bind(new InetSocketAddress(1234));
     }
}

运行结果:false

在上面代码中第一次绑定端口1234,因此,serverSocket1对象无需设置SO_REUSEADDR选项(这个选项在大多数操作系统上的默认值是false)。而serverSocket2和serverSocket3并不是第一次绑定端口1234,因此,必须设置这两个对象的SO_REUSEADDR值为true。在设置SO_REUSEADDR选项时要注意,必须在ServerSocket对象绑定端口之前设置这个选项。

也许有的读者可能有这样的疑问。如果多个ServerSocket对象同时绑定到一个端口上,那么当客户端向这个端口发出请求时,该由哪个ServerSocket对象来接收客户端请求呢?在给出答案之前,让我们先看看下面的代码的输出结果是什么。

package server;
import java.net.*;
public class TestReuseAddr2 extends Thread
{
     String s;
     public void run()
     {
         try
         {
             ServerSocket serverSocket = new ServerSocket();
             serverSocket.setReuseAddress(true);
             serverSocket.bind(new InetSocketAddress(1234));
             Socket socket = serverSocket.accept();
             System.out.println(s + ":" + socket);
             socket.close();
             serverSocket.close();
         }
         catch (Exception e)
         {
         }
     }
     public TestReuseAddr2(String s)
     {
         this.s = s;
     }
     public static void main(String[] args)
     {
         for (int i = 1; i <= 5; i++)
             new TestReuseAddr2("ServerSocket" + i).start();
     }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值