package com.netease.LDNetDiagnoService; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketTimeoutException; import java.util.List; import android.util.Log; public class LDNetSocket { private static final int PORT = 80; private static final int CONN_TIMES = 4; private static final String TIMEOUT = "DNS解析正常,连接超时,TCP建立失败"; private static final String IOERR = "DNS解析正常,IO异常,TCP建立失败"; private static final String HOSTERR = "DNS解析失败,主机地址不可达"; private static LDNetSocket instance=null; private LDNetSocketListener listener; private int timeOut = 6000;// 设置每次连接的timeout时间 public InetAddress[] _remoteInet; public List<String> _remoteIpList; private boolean[] isConnnected; private final long[] RttTimes = new long[CONN_TIMES];// 用于存储三次测试中每次的RTT值 public boolean isCConn = true; private LDNetSocket() { } public static LDNetSocket getInstance(){ if(instance==null){ instance=new LDNetSocket(); } return instance; } public void initListener(LDNetSocketListener listener){ this.listener=listener; } /** * 通过connect函数测试TCP的RTT时延 */ public boolean exec(String host) { if (isCConn && loaded) { try{ startJNITelnet(host, "80"); //默认80端口 return true; }catch(UnsatisfiedLinkError e){ e.printStackTrace(); Log.i("LDNetSocket", "call jni failed, call execUseJava"); return execUseJava(host); } } else { return execUseJava(host); } } /** * 使用java执行connected */ private boolean execUseJava(String host) { if (_remoteInet != null && _remoteIpList != null) { int len = _remoteInet.length; isConnnected = new boolean[len]; for (int i = 0; i < len; i++) { if (i != 0) { this.listener.OnNetSocketUpdated("\n"); } isConnnected[i] = execIP(_remoteInet[i], _remoteIpList.get(i)); } for (Boolean i : isConnnected) { if (i == true) {// 一个连接成功即认为成功 this.listener.OnNetSocketFinished("\n"); return true; } } } else { this.listener.OnNetSocketFinished(HOSTERR); } this.listener.OnNetSocketFinished("\n"); return false; } /** * 返回某个IP进行5次connect的最终结果 */ private boolean execIP(InetAddress inetAddress, String ip) { boolean isConnected = true; StringBuilder log = new StringBuilder(); InetSocketAddress socketAddress = null; if (inetAddress != null && ip != null) { socketAddress = new InetSocketAddress(inetAddress, PORT); int flag = 0; this.listener.OnNetSocketUpdated("Connect to host: " + ip + "..." + "\n"); for (int i = 0; i < CONN_TIMES; i++) { execSocket(socketAddress, timeOut, i); if (RttTimes[i] == -1) {// 一旦发生timeOut,则尝试加长连接时间 this.listener.OnNetSocketUpdated((i + 1) + "'s time=" + "TimeOut" + ", "); timeOut += 4000; if (i > 0 && RttTimes[i - 1] == -1) {// 连续两次连接超时,停止后续测试 flag = -1; break; } } else if (RttTimes[i] == -2) { this.listener .OnNetSocketUpdated((i + 1) + "'s time=" + "IOException"); if (i > 0 && RttTimes[i - 1] == -2) {// 连续两次出现IO异常,停止后续测试 flag = -2; break; } } else { this.listener.OnNetSocketUpdated((i + 1) + "'s time=" + RttTimes[i] + "ms, "); } } long time = 0; int count = 0; if (flag == -1) { // log.append(TIMEOUT); isConnected = false; } else if (flag == -2) { // log.append(IOERR); isConnected = false; } else { for (int i = 0; i < CONN_TIMES; i++) { if (RttTimes[i] > 0) { time += RttTimes[i]; count++; } } if (count > 0) { time = time / count; log.append("average=" + time + "ms"); } } } else { isConnected = false; } this.listener.OnNetSocketUpdated(log.toString()); return isConnected; } /** * 针对某个IP第index次connect */ private void execSocket(InetSocketAddress socketAddress, int timeOut, int index) { Socket socket = null; long start = 0; long end = 0; try { socket = new Socket(); start = System.currentTimeMillis(); socket.connect(socketAddress, timeOut); end = System.currentTimeMillis(); RttTimes[index] = end - start; } catch (SocketTimeoutException e) { RttTimes[index] = -1;// 作为TIMEOUT标识 e.printStackTrace(); } catch (IOException e) { RttTimes[index] = -2;// 作为IO异常标识 e.printStackTrace(); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } public void resetInstance() { if (instance != null) { instance = null; } } /* * 调用jni中native方法 */ public native void startJNITelnet(String host, String port); static boolean loaded; static { try { System.loadLibrary("tracepath"); loaded = true; } catch (UnsatisfiedLinkError e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } public void printSocketInfo(String log){ listener.OnNetSocketUpdated(log); } public interface LDNetSocketListener { public void OnNetSocketFinished(String log); public void OnNetSocketUpdated(String log); } }