当我使用ServerSocket类的accept方法时,谁知道端口是如何选择的?是否可以定义一个端口范围让该方法能够选择?我能否依次“取走”端口?
ServerSocket sSocket = new ServerSocket(5050);
Socket socket = sSocket.accept();
当我使用ServerSocket类的accept方法时,谁知道端口是如何选择的?是否可以定义一个端口范围让该方法能够选择?我能否依次“取走”端口?
ServerSocket sSocket = new ServerSocket(5050);
Socket socket = sSocket.accept();
这张图是错误的(在O'Reilly网站上列出了未经确认的勘误表)。
客户端随机选择它的端口(在Java中不需要特别操作),并连接到您指定的任何端口的服务器。使用命令行工具netstat
,您可以看到这一过程。
首先,只有监听服务器套接字而没有客户端:
simon@lucifer:~$ netstat -n -a Active Internet connections (including servers) Proto Recv-Q Send-Q Local Address Foreign Address (state) ... tcp46 0 0 *.5050 *.* LISTEN ...
(还有很多其他条目,我只删除了无关的内容)
现在有一个从本地主机(127.0.0.1)连接的客户端:
simon@lucifer:~$ netstat -n -a Active Internet connections (including servers) Proto Recv-Q Send-Q Local Address Foreign Address (state) ... tcp4 0 0 127.0.0.1.64895 127.0.0.1.5050 ESTABLISHED <- 1 tcp4 0 0 127.0.0.1.5050 127.0.0.1.64895 ESTABLISHED <- 2 tcp46 0 0 *.5050 *.* LISTEN <- 3 ...
因为客户端是从同一台计算机连接的,所以我们可以看到两个已建立的连接-一个从客户端到服务器(1),另一个从服务器到客户端(2)。它们具有相反的本地和外部地址(因为它们正在互相通信),并且您可以看到服务器仍在使用端口5050,而原始服务器套接字(3)继续监听同一端口。
(这个输出是来自Mac的,但Windows/Linux也有netstat
给出类似的输出)
ServerSocket定义了端口作为构造函数的一部分。 如果您没有指定端口,则套接字未绑定(即无法访问)。
要获取连接套接字的端口,请使用getPort()而不是getLocalPort()。第二个将给出您服务器上的端口。
您可以将0
作为端口号传递,以在任何空闲端口上创建服务器套接字,或者创建一个类似于以下方法的方法,以在给定范围内创建任何空闲端口的服务器套接字:
public java.net.ServerSocket createServerSocket(int rangeStart, int rangeEnd)
throws java.io.IOException {
for(int port=rangeStart; port<=randeEnd; port++) {
try {
return new ServerSocket(port);
} catch(java.net.BindException be) {
// debug/warning here
continue;
}
}
throw new java.io.IOException("Failed to create a server socket, all ports between " +
rangeStart + " - " + rangeEnd + " are already in use.");
}
SecurityException
),但您可以添加它。