Got problems on how to reuse a socket after an execution has been executed.
Down below is my code.
public class SocketUtil {
private static final String PROTOCAL_TYPE_HTTP = "http";
private static final String PROTOCAL_TYPE_HTTPS = "https";
/**
* create socket
* @param url
* @return
* @throws Exception
*/
public static Socket connect(URL url) throws Exception {
String protocal = url.getProtocol();
Socket socket;
if(PROTOCAL_TYPE_HTTP.equals(protocal)){
socket = new Socket();
} else if(PROTOCAL_TYPE_HTTPS.equals(protocal)){
SSLContext sslContext = getSslContext();
socket = sslContext.getSocketFactory().createSocket();
} else {
throw new Exception("unsupported protocal");
}
InetSocketAddress socketAddress = getSocketAddress(url);
Integer timeout = 20 * 1000;
socket.setSoTimeout(timeout);
socket.setReuseAddress(true);
socket.setTcpNoDelay(true);
socket.setKeepAlive(true);
socket.setSoLinger(true, 1000);
socket.connect(socketAddress, timeout);
return socket;
}
/**
* weather a socket is connected or not
* @param socket
* @return
*/
public static boolean isConnected(Socket socket) {
return socket != null && socket.isBound() && !socket.isClosed() && socket.isConnected()
&& !socket.isInputShutdown() && !socket.isOutputShutdown();
}
private static InetSocketAddress getSocketAddress(URL url) throws Exception {
String protocal = url.getProtocol();
Integer port = url.getPort();
if(port == -1){
if(PROTOCAL_TYPE_HTTP.equalsIgnoreCase(protocal)){
port = 80;
} else if(PROTOCAL_TYPE_HTTPS.equalsIgnoreCase(protocal)){
port = 443;
} else {
throw new Exception("unsupported protocal");
}
}
return new InetSocketAddress(InetAddress.getByName(url.getHost()), port);
}
/**
* simple ssl
* @return
* @throws Exception
*/
public static SSLContext getSslContext() throws Exception {
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, new TrustManager[]{getTrustAllManager()}, null);
return ctx;
}
/**
* trustAll
* @return
*/
private static TrustManager getTrustAllManager(){
X509TrustManager xtm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws
CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
return xtm;
}
}
And down here are my tests
@Test
public void getTest(){
try {
String apiAddress = "http://checkip.amazonaws.com";
URL url = new URL(apiAddress);
Socket socket = SocketUtil.connect(url);
for (int i = 0; i < 5; i++) {
if (!SocketUtil.isConnected(socket)) {
System.out.println("reconnect start");
socket = SocketUtil.connect(url);
}
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
printWriter.println("GET /" + url.getFile() + " HTTP/1.0");
printWriter.println("Host: " + url.getHost());
printWriter.println("");
printWriter.flush();
InputStream ins = socket.getInputStream();
String resp = IOUtils.toString(ins, "utf8");
System.out.println(resp);
}
} catch (Exception e){
e.printStackTrace();
}
}
As you can see, in my test, I run 5 executions. In the loop, the first execution runs as expected, but the other 4 executions are a little wired, I got blank messages. Anyone knows what went wrong and how to fix it?