提交 4163a25e 编写于 作者: M mbalao

8170641: sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh fails with timeout

Summary: The fix sets timeout for the server and the client, and ignore SocketTimeoutException.
Reviewed-by: chegar, phh, andrew
Contributed-by: NJohn Jiang <sha.jiang@oracle.com>
上级 40861640
/* /*
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -21,27 +21,31 @@ ...@@ -21,27 +21,31 @@
* questions. * questions.
*/ */
/*
* This test is run using PostThruProxy.sh
*/
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import java.security.KeyStore; import java.security.KeyStore;
import javax.net.*; import javax.net.*;
import javax.net.ssl.*; import javax.net.ssl.*;
import java.security.cert.*;
import jdk.testlibrary.OutputAnalyzer;
import jdk.testlibrary.ProcessTools;
/* /*
* This test case is written to test the https POST through a proxy. * @test
* There is no proxy authentication done. * @bug 4423074
* * @summary This test case is written to test the https POST through a proxy.
* PostThruProxy.java -- includes a simple server that serves * There is no proxy authentication done. It includes a simple server
* http POST method requests in secure channel, and a client * that serves http POST method requests in secure channel, and a client
* that makes https POST request through a proxy. * that makes https POST request through a proxy.
* @library /lib/testlibrary
* @compile OriginServer.java ProxyTunnelServer.java
* @run main/othervm PostThruProxy
*/ */
public class PostThruProxy { public class PostThruProxy {
private static final String TEST_SRC = System.getProperty("test.src", ".");
private static final int TIMEOUT = 30000;
/* /*
* Where do we find the keystores? * Where do we find the keystores?
*/ */
...@@ -76,14 +80,10 @@ public class PostThruProxy { ...@@ -76,14 +80,10 @@ public class PostThruProxy {
/* /*
* Main method to create the server and client * Main method to create the server and client
*/ */
public static void main(String args[]) throws Exception public static void main(String args[]) throws Exception {
{ String keyFilename = TEST_SRC + "/" + pathToStores + "/" + keyStoreFile;
String keyFilename = String trustFilename = TEST_SRC + "/" + pathToStores + "/"
args[1] + "/" + pathToStores + + trustStoreFile;
"/" + keyStoreFile;
String trustFilename =
args[1] + "/" + pathToStores +
"/" + trustStoreFile;
System.setProperty("javax.net.ssl.keyStore", keyFilename); System.setProperty("javax.net.ssl.keyStore", keyFilename);
System.setProperty("javax.net.ssl.keyStorePassword", passwd); System.setProperty("javax.net.ssl.keyStorePassword", passwd);
...@@ -95,10 +95,9 @@ public class PostThruProxy { ...@@ -95,10 +95,9 @@ public class PostThruProxy {
* setup the server * setup the server
*/ */
try { try {
ServerSocketFactory ssf = ServerSocketFactory ssf = getServerSocketFactory(useSSL);
PostThruProxy.getServerSocketFactory(useSSL);
ServerSocket ss = ssf.createServerSocket(serverPort); ServerSocket ss = ssf.createServerSocket(serverPort);
ss.setSoTimeout(30000); // 30 seconds ss.setSoTimeout(TIMEOUT); // 30 seconds
serverPort = ss.getLocalPort(); serverPort = ss.getLocalPort();
new TestServer(ss); new TestServer(ss);
} catch (Exception e) { } catch (Exception e) {
...@@ -108,35 +107,29 @@ public class PostThruProxy { ...@@ -108,35 +107,29 @@ public class PostThruProxy {
} }
// trigger the client // trigger the client
try { try {
doClientSide(args[0]); doClientSide();
} catch (Exception e) { } catch (Exception e) {
System.out.println("Client side failed: " + System.out.println("Client side failed: " +
e.getMessage()); e.getMessage());
throw e; throw e;
} }
} }
private static ServerSocketFactory getServerSocketFactory private static ServerSocketFactory getServerSocketFactory
(boolean useSSL) throws Exception { (boolean useSSL) throws Exception {
if (useSSL) { if (useSSL) {
SSLServerSocketFactory ssf = null;
// set up key manager to do server authentication // set up key manager to do server authentication
SSLContext ctx; SSLContext ctx = SSLContext.getInstance("TLS");
KeyManagerFactory kmf; KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
KeyStore ks; KeyStore ks = KeyStore.getInstance("JKS");
char[] passphrase = passwd.toCharArray(); char[] passphrase = passwd.toCharArray();
ctx = SSLContext.getInstance("TLS");
kmf = KeyManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(System.getProperty( ks.load(new FileInputStream(System.getProperty(
"javax.net.ssl.keyStore")), passphrase); "javax.net.ssl.keyStore")), passphrase);
kmf.init(ks, passphrase); kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), null, null); ctx.init(kmf.getKeyManagers(), null, null);
ssf = ctx.getServerSocketFactory(); return ctx.getServerSocketFactory();
return ssf;
} else { } else {
return ServerSocketFactory.getDefault(); return ServerSocketFactory.getDefault();
} }
...@@ -147,7 +140,7 @@ public class PostThruProxy { ...@@ -147,7 +140,7 @@ public class PostThruProxy {
*/ */
static String postMsg = "Testing HTTP post on a https server"; static String postMsg = "Testing HTTP post on a https server";
static void doClientSide(String hostname) throws Exception { static void doClientSide() throws Exception {
HostnameVerifier reservedHV = HostnameVerifier reservedHV =
HttpsURLConnection.getDefaultHostnameVerifier(); HttpsURLConnection.getDefaultHostnameVerifier();
try { try {
...@@ -162,10 +155,12 @@ public class PostThruProxy { ...@@ -162,10 +155,12 @@ public class PostThruProxy {
*/ */
HttpsURLConnection.setDefaultHostnameVerifier( HttpsURLConnection.setDefaultHostnameVerifier(
new NameVerifier()); new NameVerifier());
URL url = new URL("https://" + hostname+ ":" + serverPort); URL url = new URL("https://" + getHostname() +":" + serverPort);
Proxy p = new Proxy(Proxy.Type.HTTP, pAddr); Proxy p = new Proxy(Proxy.Type.HTTP, pAddr);
HttpsURLConnection https = (HttpsURLConnection)url.openConnection(p); HttpsURLConnection https = (HttpsURLConnection)url.openConnection(p);
https.setConnectTimeout(TIMEOUT);
https.setReadTimeout(TIMEOUT);
https.setDoOutput(true); https.setDoOutput(true);
https.setRequestMethod("POST"); https.setRequestMethod("POST");
PrintStream ps = null; PrintStream ps = null;
...@@ -190,6 +185,9 @@ public class PostThruProxy { ...@@ -190,6 +185,9 @@ public class PostThruProxy {
if (ps != null) if (ps != null)
ps.close(); ps.close();
throw e; throw e;
} catch (SocketTimeoutException e) {
System.out.println("Client can not get response in time: "
+ e.getMessage());
} }
} finally { } finally {
HttpsURLConnection.setDefaultHostnameVerifier(reservedHV); HttpsURLConnection.setDefaultHostnameVerifier(reservedHV);
...@@ -210,4 +208,13 @@ public class PostThruProxy { ...@@ -210,4 +208,13 @@ public class PostThruProxy {
pserver.start(); pserver.start();
return new InetSocketAddress("localhost", pserver.getPort()); return new InetSocketAddress("localhost", pserver.getPort());
} }
private static String getHostname() {
try {
OutputAnalyzer oa = ProcessTools.executeCommand("hostname");
return oa.getOutput().trim();
} catch (Throwable e) {
throw new RuntimeException("Get hostname failed.", e);
}
}
} }
#!/bin/sh
#
# Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
# @test
# @bug 4423074
# @summary Need to rebase all the duplicated classes from Merlin
HOSTNAME=`uname -n`
OS=`uname -s`
case "$OS" in
SunOS | Linux | Darwin | AIX )
PS=":"
FS="/"
;;
CYGWIN* )
PS=";"
FS="/"
;;
Windows* )
PS=";"
FS="\\"
;;
* )
echo "Unrecognized system!"
exit 1;
;;
esac
${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . \
${TESTSRC}${FS}OriginServer.java \
${TESTSRC}${FS}ProxyTunnelServer.java \
${TESTSRC}${FS}PostThruProxy.java
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} PostThruProxy ${HOSTNAME} ${TESTSRC}
exit
/* /*
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -21,28 +21,31 @@ ...@@ -21,28 +21,31 @@
* questions. * questions.
*/ */
/*
* This test is run through PostThruProxyWithAuth.sh
*/
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import java.security.KeyStore; import java.security.KeyStore;
import javax.net.*; import javax.net.*;
import javax.net.ssl.*; import javax.net.ssl.*;
import java.security.cert.*;
import jdk.testlibrary.OutputAnalyzer;
import jdk.testlibrary.ProcessTools;
/* /*
* This test case is written to test the https POST through a proxy * @test
* with proxy authentication. * @bug 4423074
* * @summary This test case is written to test the https POST through a proxy
* PostThruProxyWithAuth.java -- includes a simple server that serves * with proxy authentication. It includes a simple server that serves
* http POST method requests in secure channel, and a client * http POST method requests in secure channel, and a client that
* that makes https POST request through a proxy. * makes https POST request through a proxy.
* @library /lib/testlibrary
* @compile OriginServer.java ProxyTunnelServer.java
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes= PostThruProxyWithAuth
*/ */
public class PostThruProxyWithAuth { public class PostThruProxyWithAuth {
private static final String TEST_SRC = System.getProperty("test.src", ".");
private static final int TIMEOUT = 30000;
/* /*
* Where do we find the keystores? * Where do we find the keystores?
*/ */
...@@ -78,14 +81,10 @@ public class PostThruProxyWithAuth { ...@@ -78,14 +81,10 @@ public class PostThruProxyWithAuth {
/* /*
* Main method to create the server and client * Main method to create the server and client
*/ */
public static void main(String args[]) throws Exception public static void main(String args[]) throws Exception {
{ String keyFilename = TEST_SRC + "/" + pathToStores + "/" + keyStoreFile;
String keyFilename = String trustFilename = TEST_SRC + "/" + pathToStores + "/"
args[1] + "/" + pathToStores + + trustStoreFile;
"/" + keyStoreFile;
String trustFilename =
args[1] + "/" + pathToStores +
"/" + trustStoreFile;
System.setProperty("javax.net.ssl.keyStore", keyFilename); System.setProperty("javax.net.ssl.keyStore", keyFilename);
System.setProperty("javax.net.ssl.keyStorePassword", passwd); System.setProperty("javax.net.ssl.keyStorePassword", passwd);
...@@ -97,10 +96,9 @@ public class PostThruProxyWithAuth { ...@@ -97,10 +96,9 @@ public class PostThruProxyWithAuth {
* setup the server * setup the server
*/ */
try { try {
ServerSocketFactory ssf = ServerSocketFactory ssf = getServerSocketFactory(useSSL);
PostThruProxyWithAuth.getServerSocketFactory(useSSL);
ServerSocket ss = ssf.createServerSocket(serverPort); ServerSocket ss = ssf.createServerSocket(serverPort);
ss.setSoTimeout(30000); // 30 seconds ss.setSoTimeout(TIMEOUT); // 30 seconds
serverPort = ss.getLocalPort(); serverPort = ss.getLocalPort();
new TestServer(ss); new TestServer(ss);
} catch (Exception e) { } catch (Exception e) {
...@@ -110,7 +108,7 @@ public class PostThruProxyWithAuth { ...@@ -110,7 +108,7 @@ public class PostThruProxyWithAuth {
} }
// trigger the client // trigger the client
try { try {
doClientSide(args[0]); doClientSide();
} catch (Exception e) { } catch (Exception e) {
System.out.println("Client side failed: " + System.out.println("Client side failed: " +
e.getMessage()); e.getMessage());
...@@ -121,24 +119,18 @@ public class PostThruProxyWithAuth { ...@@ -121,24 +119,18 @@ public class PostThruProxyWithAuth {
private static ServerSocketFactory getServerSocketFactory private static ServerSocketFactory getServerSocketFactory
(boolean useSSL) throws Exception { (boolean useSSL) throws Exception {
if (useSSL) { if (useSSL) {
SSLServerSocketFactory ssf = null;
// set up key manager to do server authentication // set up key manager to do server authentication
SSLContext ctx; SSLContext ctx = SSLContext.getInstance("TLS");
KeyManagerFactory kmf; KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
KeyStore ks; KeyStore ks = KeyStore.getInstance("JKS");
char[] passphrase = passwd.toCharArray(); char[] passphrase = passwd.toCharArray();
ctx = SSLContext.getInstance("TLS");
kmf = KeyManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(System.getProperty( ks.load(new FileInputStream(System.getProperty(
"javax.net.ssl.keyStore")), passphrase); "javax.net.ssl.keyStore")), passphrase);
kmf.init(ks, passphrase); kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), null, null); ctx.init(kmf.getKeyManagers(), null, null);
ssf = ctx.getServerSocketFactory(); return ctx.getServerSocketFactory();
return ssf;
} else { } else {
return ServerSocketFactory.getDefault(); return ServerSocketFactory.getDefault();
} }
...@@ -149,7 +141,7 @@ public class PostThruProxyWithAuth { ...@@ -149,7 +141,7 @@ public class PostThruProxyWithAuth {
*/ */
static String postMsg = "Testing HTTP post on a https server"; static String postMsg = "Testing HTTP post on a https server";
static void doClientSide(String hostname) throws Exception { static void doClientSide() throws Exception {
/* /*
* setup up a proxy * setup up a proxy
*/ */
...@@ -161,10 +153,12 @@ public class PostThruProxyWithAuth { ...@@ -161,10 +153,12 @@ public class PostThruProxyWithAuth {
*/ */
HttpsURLConnection.setDefaultHostnameVerifier( HttpsURLConnection.setDefaultHostnameVerifier(
new NameVerifier()); new NameVerifier());
URL url = new URL("https://" + hostname + ":" + serverPort); URL url = new URL("https://" + getHostname() + ":" + serverPort);
Proxy p = new Proxy(Proxy.Type.HTTP, pAddr); Proxy p = new Proxy(Proxy.Type.HTTP, pAddr);
HttpsURLConnection https = (HttpsURLConnection)url.openConnection(p); HttpsURLConnection https = (HttpsURLConnection)url.openConnection(p);
https.setConnectTimeout(TIMEOUT);
https.setReadTimeout(TIMEOUT);
https.setDoOutput(true); https.setDoOutput(true);
https.setRequestMethod("POST"); https.setRequestMethod("POST");
PrintStream ps = null; PrintStream ps = null;
...@@ -188,6 +182,9 @@ public class PostThruProxyWithAuth { ...@@ -188,6 +182,9 @@ public class PostThruProxyWithAuth {
if (ps != null) if (ps != null)
ps.close(); ps.close();
throw e; throw e;
} catch (SocketTimeoutException e) {
System.out.println("Client can not get response in time: "
+ e.getMessage());
} }
} }
...@@ -221,4 +218,13 @@ public class PostThruProxyWithAuth { ...@@ -221,4 +218,13 @@ public class PostThruProxyWithAuth {
"test123".toCharArray()); "test123".toCharArray());
} }
} }
private static String getHostname() {
try {
OutputAnalyzer oa = ProcessTools.executeCommand("hostname");
return oa.getOutput().trim();
} catch (Throwable e) {
throw new RuntimeException("Get hostname failed.", e);
}
}
} }
#!/bin/sh
#
# Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
# @test
# @bug 4423074
# @summary Need to rebase all the duplicated classes from Merlin
HOSTNAME=`uname -n`
OS=`uname -s`
case "$OS" in
SunOS | Linux | Darwin | AIX )
PS=":"
FS="/"
;;
CYGWIN* )
PS=";"
FS="/"
;;
Windows* )
PS=";"
FS="\\"
;;
* )
echo "Unrecognized system!"
exit 1;
;;
esac
${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . ${TESTSRC}${FS}OriginServer.java \
${TESTSRC}${FS}ProxyTunnelServer.java \
${TESTSRC}${FS}PostThruProxyWithAuth.java
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \
-Djdk.http.auth.tunneling.disabledSchemes= \
PostThruProxyWithAuth ${HOSTNAME} ${TESTSRC}
exit
/* /*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -32,13 +32,14 @@ ...@@ -32,13 +32,14 @@
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import javax.net.ssl.*;
import javax.net.ServerSocketFactory; import javax.net.ServerSocketFactory;
import sun.net.www.*; import sun.net.www.*;
import java.util.Base64; import java.util.Base64;
public class ProxyTunnelServer extends Thread { public class ProxyTunnelServer extends Thread {
private static final int TIMEOUT = 30000;
private static ServerSocket ss = null; private static ServerSocket ss = null;
/* /*
* holds the registered user's username and password * holds the registered user's username and password
...@@ -64,8 +65,9 @@ public class ProxyTunnelServer extends Thread { ...@@ -64,8 +65,9 @@ public class ProxyTunnelServer extends Thread {
public ProxyTunnelServer() throws IOException { public ProxyTunnelServer() throws IOException {
if (ss == null) { if (ss == null) {
ss = (ServerSocket) ServerSocketFactory.getDefault(). ss = (ServerSocket) ServerSocketFactory.getDefault()
createServerSocket(0); .createServerSocket(0);
ss.setSoTimeout(TIMEOUT);
} }
} }
...@@ -86,6 +88,9 @@ public class ProxyTunnelServer extends Thread { ...@@ -86,6 +88,9 @@ public class ProxyTunnelServer extends Thread {
try { try {
clientSocket = ss.accept(); clientSocket = ss.accept();
processRequests(); processRequests();
} catch (SocketTimeoutException e) {
System.out.println(
"Proxy can not get response in time: " + e.getMessage());
} catch (Exception e) { } catch (Exception e) {
System.out.println("Proxy Failed: " + e); System.out.println("Proxy Failed: " + e);
e.printStackTrace(); e.printStackTrace();
...@@ -188,8 +193,8 @@ public class ProxyTunnelServer extends Thread { ...@@ -188,8 +193,8 @@ public class ProxyTunnelServer extends Thread {
serverToClient.start(); serverToClient.start();
System.out.println("Proxy: Started tunneling......."); System.out.println("Proxy: Started tunneling.......");
clientToServer.join(); clientToServer.join(TIMEOUT);
serverToClient.join(); serverToClient.join(TIMEOUT);
System.out.println("Proxy: Finished tunneling........"); System.out.println("Proxy: Finished tunneling........");
clientToServer.close(); clientToServer.close();
...@@ -219,13 +224,11 @@ public class ProxyTunnelServer extends Thread { ...@@ -219,13 +224,11 @@ public class ProxyTunnelServer extends Thread {
int BUFFER_SIZE = 400; int BUFFER_SIZE = 400;
byte[] buf = new byte[BUFFER_SIZE]; byte[] buf = new byte[BUFFER_SIZE];
int bytesRead = 0; int bytesRead = 0;
int count = 0; // keep track of the amount of data transfer
try { try {
while ((bytesRead = input.read(buf)) >= 0) { while ((bytesRead = input.read(buf)) >= 0) {
output.write(buf, 0, bytesRead); output.write(buf, 0, bytesRead);
output.flush(); output.flush();
count += bytesRead;
} }
} catch (IOException e) { } catch (IOException e) {
/* /*
...@@ -236,7 +239,7 @@ public class ProxyTunnelServer extends Thread { ...@@ -236,7 +239,7 @@ public class ProxyTunnelServer extends Thread {
} }
} }
public void close() { private void close() {
try { try {
if (!sockIn.isClosed()) if (!sockIn.isClosed())
sockIn.close(); sockIn.close();
...@@ -275,7 +278,7 @@ public class ProxyTunnelServer extends Thread { ...@@ -275,7 +278,7 @@ public class ProxyTunnelServer extends Thread {
serverPort = Integer.parseInt(connectInfo.substring(endi+1)); serverPort = Integer.parseInt(connectInfo.substring(endi+1));
} catch (Exception e) { } catch (Exception e) {
throw new IOException("Proxy recieved a request: " throw new IOException("Proxy recieved a request: "
+ connectStr); + connectStr, e);
} }
serverInetAddr = InetAddress.getByName(serverName); serverInetAddr = InetAddress.getByName(serverName);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册