【TCP/IP】TCP即时通讯判断网络状态和断线重连机制

TCP即时通讯判断网络状态和断线重连机制

  1. 由于近半年来一直写针对于tigase服务器的即时通讯软件的开发,框架的重构,对即时通讯的理解也较之前更进一步,在客户端的IM开发中,最重要的除去通讯的建立,就是保持网络环境不断更换时,客户端与服务器端的长连接。
  • 具体实现的思路:
    由于客户端网络状况不稳定,客户端通过加入判断网路状态的工具类,来判断网路是否重新连接,一旦网路状态从无到有,便开启断线重连机制,重新登陆IM服务器,登陆成功后,阻塞当前线程
  1. 判断网络状态的工具类
public class NetWorkUtils {  
  
    /** 
     * 没有网络 
     */  
    public static final String NETWORKTYPE_INVALID = "NO";  
  
    /** 
     * 2G网络 
     */  
    public static final String NETWORKTYPE_2G = "2G";  
    /** 
     * 3G 
     */  
    public static final String NETWORKTYPE_3G = "3G";  
    /** 
     * 4G 
     */  
    public static final String NETWORKTYPE_4G = "4G";  
    /** 
     * wifi网络 
     */  
    public static final String NETWORKTYPE_WIFI = "WIFI";  
  
    /** 
     * wifi网络 
     */  
    public static final String NETWORKTYPE_UNKNOWN = "UNKNOWN";  
  
  
    /** 
     * 获取当前网络类型 
     * 
     * @param context 
     * @return 2G/3G/4G/WIFI/no/unknown 
     */  
    public static String getNetType(Context context) {  
        ConnectivityManager cm = (ConnectivityManager) context  
                .getSystemService(Context.CONNECTIVITY_SERVICE);  
        final NetworkInfo info = cm.getActiveNetworkInfo();  
        if (info == null || !info.isAvailable()) {  
            return NETWORKTYPE_INVALID;  
        }  
        if (info.getType() == ConnectivityManager.TYPE_WIFI) {  
            return NETWORKTYPE_WIFI;  
        }  
        if (info.getType() == ConnectivityManager.TYPE_MOBILE) {  
            int sub = info.getSubtype();  
  
            L.d("asker","网络类型"+sub);  
            switch (sub) {  
  
                case TelephonyManager.NETWORK_TYPE_GPRS:  
                case TelephonyManager.NETWORK_TYPE_EDGE:  
                case TelephonyManager.NETWORK_TYPE_CDMA://电信的2G  
                case TelephonyManager.NETWORK_TYPE_1xRTT:  
                case TelephonyManager.NETWORK_TYPE_IDEN:  
                    //以上的都是2G网络  
                    return NETWORKTYPE_2G;  
  
                case TelephonyManager.NETWORK_TYPE_UMTS:  
                case TelephonyManager.NETWORK_TYPE_EVDO_A:  
                case TelephonyManager.NETWORK_TYPE_HSDPA:  
                case TelephonyManager.NETWORK_TYPE_HSUPA:  
                case TelephonyManager.NETWORK_TYPE_HSPA:  
                case TelephonyManager.NETWORK_TYPE_EVDO_B:  
                case TelephonyManager.NETWORK_TYPE_EHRPD:  
                case TelephonyManager.NETWORK_TYPE_HSPAP:  
                    //以上的都是3G网络  
                    return NETWORKTYPE_3G;  
  
                case TelephonyManager.NETWORK_TYPE_LTE:  
                case 18:  
  
                    return NETWORKTYPE_4G;  
  
                case TelephonyManager.NETWORK_TYPE_UNKNOWN:  
  
                    return NETWORKTYPE_INVALID;  
  
                default:  
                    return NETWORKTYPE_UNKNOWN;  
            }  
        }  
        return NETWORKTYPE_UNKNOWN;  
  
    }  
  
  
    /* 
    * 获取IP地址 
    * 
    * */  
    public static String getIPAddress(Context context) {  
  
        if (NETWORKTYPE_WIFI.equals(getNetType(context))) {  
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);  
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();  
            // 获取32位整型IP地址  
            int ipAddress = wifiInfo.getIpAddress();  
  
            //返回整型地址转换成“*.*.*.*”地址  
            return String.format("%d.%d.%d.%d",  
                    (ipAddress & 0xff), (ipAddress >> 8 & 0xff),  
                    (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff));  
        } else {  
            try {  
                for (Enumeration<NetworkInterface> en = NetworkInterface  
                        .getNetworkInterfaces(); en.hasMoreElements(); ) {  
                    NetworkInterface intf = en.nextElement();  
                    for (Enumeration<InetAddress> enumIpAddr = intf  
                            .getInetAddresses(); enumIpAddr.hasMoreElements(); ) {  
                        InetAddress inetAddress = enumIpAddr.nextElement();  
                        if (!inetAddress.isLoopbackAddress()  
                                && inetAddress instanceof Inet4Address) {  
                            // if (!inetAddress.isLoopbackAddress() && inetAddress  
                            // instanceof Inet6Address) {  
                            return inetAddress.getHostAddress().toString();  
                        }  
                    }  
                }  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
            return "";  
  
        }  
    }  
}  
  1. 断线重连机制
[java] view plain copy
/** 
 * 断线重连机制 
 * Created by fflin on 2016/5/8. 
 */  
public class ReconnectionThread extends Thread {  
    private LoginService loginService;  
    private int reconnectCount;  
    public ReconnectionThread(LoginService service) {  
        this.loginService = service;  
        this.reconnectCount = 0;  
    }  
  
    @Override  
    public void run() {  
        try {  
            while (!isInterrupted()) {  
                L.e("asker", "@@ 正在断线重连 " + waitingTime()  
                        + " seconds" + "; UrlConstant.jaxmpp.isConnected() :" + UrlConstant.jaxmpp.isConnected()  
                        + "; isInterrupted() :" + isInterrupted());  
                Thread.sleep((long) waitingTime() * 1000l);  
                if (!UrlConstant.jaxmpp.isConnected()){  
                    loginService.Login(); //重新登陆聊天服务器  
                    reconnectCount++;  
                }else{  
                    currentThread().interrupt(); //登陆成功阻塞当前线程  
                }  
            }  
  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
  
    }  
  
    private int waitingTime() {  
        if (reconnectCount > 20) {  
            return 600;  
        }  
        if (reconnectCount > 13) {  
            return 300;  
        }  
        return reconnectCount <= 7 ? 5 : 60;  
    }  
  
}  

你可能感兴趣的:(Socket,TCP)