我想启动一个监听端口的服务器.我可以明确指定端口,它可以工作.但我想以自动方式找到一个端口.在这方面,我有两个问题.
我应该在哪个端口号范围内搜索?(我使用了端口12345,12346和12347,它很好).
如何确定某个端口是否未被其他软件占用?
描述
我做了一个JUnit测试,专注于尝试测试对SOAP Web服务的调用.
我正在使用嵌入式tomcat服务器进行测试,以便使用模拟服务器运行我的测试.
我也使用http和https连接器.
我需要为这两个连接器使用自动端口,因为测试在Jenkins服务器上运行,我不能只使用端口443或8443,因为它们已被占用.
我知道使用端口0作为标准端口将导致tomcat使用自动端口分配,但我无法使用它与两个连接器.
预期的行为
我也想为我的自定义ssl连接器使用自动端口分配.
是否有可能以某种方式这样做?
示例代码
这是我的tomcat实例的代码:
@Before
public void setup() throws Throwable {
File tomcatWorkingDir = new File(mWorkingDir);
//Empty the target/tomcat-working-dir directory if it exist
//Create the directory otherwise
if(tomcatWorkingDir.exists() && tomcatWorkingDir.isDirectory()){
LOGGER.info("cleaning tomcat-working-dir directory");
FileUtils.cleanDirectory(new File(mWorkingDir));
} else {
LOGGER.info("create tomcat-working-dir directory");
tomcatWorkingDir.mkdir();
}
LOGGER.info("disabling ssl certification validation");
//Disable JVM ssl sockets connection
disableJVMCertificate();
//Add server certificate
createServerCertificate();
//Custom SSL Connector
Connector SSLConnector = getSSLConnector();
mTomcat = new Tomcat();
//Standard http startup port …Run Code Online (Sandbox Code Playgroud) 如果你愿意,你可以跳过这个故事.还有一些人可能会感兴趣.
我有一个Java嵌入式ZooKeeper服务器.在单元测试中,我将端口分配给测试服务器.在分配端口之前,我通过打开a来检查它是否未使用ServerSocket,然后关闭它.
它不时发生,在BindException我启动我的服务器时得到的单元测试中(我不能将相同的端口分配给两个服务器,因为我使用文件锁也可以进行互斥).事实证明,原因是,对于端口检查我打开端口,然后我关闭它,它等待一段时间在操作系统级别,直到端口可以重新打开.
但是有一个选项(StandardSocketOptions.SO_REUSEADDR)可以告诉Java套接字,可以重用TIMED_WAIT状态的旧套接字.检查ZooKeeper代码后,它实际上设置为true(请参阅org.apache.zookeeper.server.NIOServerCnxnFactory.configure(InetSocketAddress,int)):
@Override
public void configure(InetSocketAddress addr, int maxcc) throws IOException {
configureSaslLogin();
thread = new Thread(this, "NIOServerCxn.Factory:" + addr);
thread.setDaemon(true);
maxClientCnxns = maxcc;
this.ss = ServerSocketChannel.open();
ss.socket().setReuseAddress(true);
LOG.info("binding to port " + addr);
ss.socket().bind(addr);
ss.configureBlocking(false);
ss.register(selector, SelectionKey.OP_ACCEPT);
}
Run Code Online (Sandbox Code Playgroud)
然而,我的测试证明它不起作用.我得到BindException(在Linux JDK 1.7.0_60下).
在检查了ServerSocketChannel实现(JDK 1.7.0_60)后,我意识到,这绝不会在linux下工作.见sun.nio.ch.ServerSocketChannelImpl.setOption(SocketOption<T>, T):
public <T> ServerSocketChannel setOption(SocketOption<T> paramSocketOption, T paramT) throws IOException
{
if (paramSocketOption == null)
throw new NullPointerException();
if …Run Code Online (Sandbox Code Playgroud) 我正在尝试模拟我的程序的各种运行的测试,在@Before方法中设置Jetty服务器并在一个方法中关闭它@After.
我的第一个测试将成功运行,但在尝试POST数据com.sun.jersey.api.client.ClientHandlerException: java.net.SocketException: Software caused connection abort: recv failed时会发生以下测试.有什么方法可以让我的服务器(和客户端?)在测试之间干净地关闭?
我的Before和After代码如下:
@Before
public void startServer() {
try {
server = new Server(8080);
ServletContextHandler root = new ServletContextHandler(server, "/ingest", ServletContextHandler.SESSIONS);
root.addServlet(new Servlet(), "/*");
server.start();
client = new Client();
client.setChunkedEncodingSize(16 * 1024);
FileInputStream stream = new FileInputStream(testFile);
try {
client.resource(uri).type(MediaType.APPLICATION_OCTET_STREAM).post(stream);
} catch (Exception e) {
e.printStackTrace();
} finally {
Closeables.closeQuietly(stream);
client.destroy();
}
} catch (Exception e) {
e.printStackTrace();
fail("Unexpected Exception when starting up server.");
}
}
@After …Run Code Online (Sandbox Code Playgroud) 我需要发现远程服务器上的开放端口.我想知道这是否可行.我在想我打开一个套接字,如果这个成功,就意味着它被使用了......否则,如果我得到一个异常,那么就不会使用它.
例如,
public boolean isActive() {
Socket s = null;
try {
s = new Socket();
s.setReuseAddress(true);
SocketAddress sa = new InetSocketAddress(this.host, this.port);
s.connect(sa, 3000);
return true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (s != null) {
try {
s.close();
} catch (IOException e) {
}
}
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
这是一种可行的方法吗?
我理解以下代码可以(可能不是非常有效)在Java中找到一个免费的TCP端口:
public static int findFreePort() {
int port;
try {
ServerSocket socket= new ServerSocket(0);
port = socket.getLocalPort();
socket.close();
} catch (Exception e) { port = -1; }
return port;
}
Run Code Online (Sandbox Code Playgroud)
我不明白的原因是,为什么(或者是否)对这种方法的两次成功调用保证返回两个不同的端口.例如,这里假设(搜索findFreePort方法调用).
它是否正确?
我一直在尝试创建一个需要尽快扫描网络(主要是LAN)上的开放端口的应用程序.
我搜索了一下,我找到的一个很好的方法使用以下代码:
(1 to 65536).par.map { case port ?
try {
val socket = new java.net.Socket("127.0.0.1", port)
socket.close()
println(port)
port
} catch {
case _: Throwable ? -1
}
}.toSet
Run Code Online (Sandbox Code Playgroud)
但是,代码的问题是,如果我输入127.0.0.1以外的任何内容或localhost作为位置(比如192.168.1.2),应用程序会冻结.
知道为什么会这样,以及我如何解决它?
PS我也尝试用socket.setSoTimeout(1500)设置套接字超时,但没有变化.
我正在研究java.我如何检查端口是否可以免费使用ServerSocket?此外,当accept()函数返回Socket时,它默认给出一个端口和IP地址,或者我也必须指定它?