android smack java.net.ConnectException 连接被拒绝

android smack java.net.ConnectException Connection refused

我正在尝试使用 smack/xmpp 编写聊天应用程序。 我安装了 ejabberd 服务器。我的程序很好地连接到它并且可以发送 给其他客户的消息。 XMPP 服务有 STICKY 属性。 运行 重度应用程序(如 3d 游戏)后出现问题。 玩游戏时,xmpp 连接服务器断开,退出游戏后服务自动重启并尝试再次连接,但出现 SMACKException:

09-20 15:46:06.540 31467-31533/home.chat E/(onCreate):SMACKException: The following addresses failed: '94.x.x.x:5222' failed because java.net.ConnectException: failed to connect to /94.x.x.x (port 5222) after 30000ms: isConnected failed: ECONNREFUSED (Connection refused)

我看了这个错误的解释,意思是: 尝试将套接字连接到远程地址和端口时发生错误的信号。通常,连接被远程拒绝(例如,没有进程正在侦听远程 address/port)。

在我的 xmpp 服务中,我有重新连接管理器。在某些情况下它工作正常,但在这种情况下它没有任何作用。

捕捉到这个异常后,我尝试以编程方式重新启动服务,但这没有帮助。 只有手动卸载和重新启动应用程序有帮助。 我认为服务器在超时 30 秒后关闭 xmpp 连接,但为什么重新加载服务没有给出结果? 有谁知道我的代码是否有问题?

我的服务class 包裹 home.chat;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

import java.io.File;
import java.util.Date;

public class MyService extends Service {
private static String DOMAIN = GlobalVariables.server;
private static String USERNAME = GlobalVariables.user_id;
private static String PASSWORD = GlobalVariables.user_password;
public static MyXMPP xmpp;
String text = "";
private LocalDb ldb;
private Boolean disconnectAppeared = false;
BroadcastReceiver br = null;
Date d1 = null;
Date d2 = null;
static MyService instance;

public static MyService getInstance(){
    return instance;
}

@Override
public IBinder onBind(final Intent intent) {
    return new LocalBinder<MyService>(this);
}

@Override
public void onCreate() {
    super.onCreate();
    instance = this;
    checkInternetConnection();
    xmpp = MyXMPP.getInstance(MyService.this, DOMAIN, USERNAME, PASSWORD);
    connect();

    Log.e("MyService"," created");
}

public static void connect(){
    xmpp.connect("onCreate");
}

@Override
public int onStartCommand(final Intent intent, final int flags,
                          final int startId) {
    return Service.START_STICKY;
}

@Override
public boolean onUnbind(final Intent intent) {
    return super.onUnbind(intent);
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.e("MyService"," destroyed");
    xmpp.disconnect();
    unregisterReceiver(br);
    Log.i("EXIT", "ondestroy!");
    Intent broadcastIntent = new Intent("home.chat.ActivityRecognition.RestartService");
    sendBroadcast(broadcastIntent);
}

private void checkInternetConnection() {
    if (br == null) {
        br = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                Bundle extras = intent.getExtras();
                NetworkInfo info = (NetworkInfo) extras
                        .getParcelable("networkInfo");
                NetworkInfo.State state = info.getState();
                Log.d("TEST Internet", info.toString() + " "
                        + state.toString());
                if (state == NetworkInfo.State.CONNECTED & disconnectAppeared) { //on
                        xmpp.connect("After network changes");
                    disconnectAppeared = false;
                }
                if (state == NetworkInfo.State.DISCONNECTED) { //off
                    disconnectAppeared = true;
                }
            }
        };
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(br, intentFilter);
    }
}
public void destroyService(){
    stopSelf();
}
}

MyXMPPclass

package home.chat;

import *;

public class MyXMPP {

public static boolean connected = false;
public static boolean loggedin = false;
public static boolean isconnecting = false;
public static boolean isToasted = false;
private boolean chat_created = false;
private String serverAddress;
public static XMPPTCPConnection connection;
public static String loginUser;
public static String passwordUser;
Gson gson;
static MyService context;
public static MyXMPP instance = null;
public static boolean instanceCreated = false;
private Handler mHandler = new Handler();
public static ReconnectionManager connMgr;
int[] rt_arr = {2,2,2,5,5,10,10};
int curr_delay = 0;
public static ConnectivityManager cm = null;
public NetworkInfo activeNetwork = null;
public static Roster myRoster;

static ArrayList<ChatMessage> msg_array = new ArrayList<ChatMessage>(); //буфер сообщений для отправки
public static ArrayList<HashMap<String,String>> msg_queue = new ArrayList<>();
public static ArrayList<HashMap<String,String>> stat_list = new ArrayList<>();
public String senderName = "";

public MyXMPP(MyService context, String serverAdress, String logiUser,
              String passwordser) {
    this.serverAddress = serverAdress;
    this.loginUser = logiUser;
    this.passwordUser = passwordser;
    this.context = context;
    init();
}

public static MyXMPP getInstance(MyService context, String server,
                                 String user, String pass) {
    if (instance == null) {
        instance = new MyXMPP(context, server, user, pass);
        instanceCreated = true;
        Log.e("MyXMPP","create new instance");
    }
    return instance;
}

public org.jivesoftware.smack.chat.Chat Mychat;

ChatManagerListenerImpl mChatManagerListener;
MMessageListener mMessageListener;

String text = "";
String mMessage = "", mReceiver = "";

static {
    try {
        Class.forName("org.jivesoftware.smack.ReconnectionManager");
    } catch (ClassNotFoundException ex) {
        Log.e("E:","problem loading reconnection manager");
        // problem loading reconnection manager
    }
}

public void init() {
    gson = new Gson();
    mMessageListener = new MMessageListener();
    mChatManagerListener = new ChatManagerListenerImpl();
    initialiseConnection();
}

private void initialiseConnection() {

    cm =
            (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    activeNetwork = cm.getActiveNetworkInfo();

    XMPPTCPConnectionConfiguration.Builder config = XMPPTCPConnectionConfiguration
            .builder();
    config.setSendPresence(true);
    config.setSecurityMode(XMPPTCPConnectionConfiguration.SecurityMode.required);
    config.setCompressionEnabled(true);
    config.setServiceName(GlobalVariables.service);
    config.setHost(serverAddress);
    config.setPort(5222);
    config.setDebuggerEnabled(true);

    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        MemorizingTrustManager mtm = new MemorizingTrustManager(context);
        sc.init(null, new X509TrustManager[] { mtm }, new java.security.SecureRandom());
        config.setCustomSSLContext(sc);
        config.setHostnameVerifier(mtm.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier()));
    } catch (NoSuchAlgorithmException e) {
        throw new IllegalStateException(e);
    } catch (KeyManagementException e) {
        throw new IllegalStateException(e);
    }
    connection = new XMPPTCPConnection(config.build());
    XMPPConnectionListener connectionListener = new XMPPConnectionListener();
    connection.addConnectionListener(connectionListener);

    PingManager pingManager = PingManager.getInstanceFor(connection);
    pingManager.setPingInterval(900); // 15 min
    pingManager.registerPingFailedListener(new PingFailedListener(){
        @Override
        public void pingFailed() {
            // Do operation to handle if ping fail like force reconnect etc
            Log.e("PingManager","Ping Failed, reconnection");
            connected = false;
            chat_created = false;
            loggedin = false;
            //disconnect();
            connect("ping_manager");
        }

    });
    ServerPingWithAlarmManager.getInstanceFor(connection).isEnabled(); //для пинга во время глубокого сна
}

public void disconnect() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            connection.disconnect();
        }
    }).start();
}

public void connect(final String caller) {
    AsyncTask<Void, Void, Boolean> connectionThread = new AsyncTask<Void, Void, Boolean>() {
        @Override
        protected synchronized Boolean doInBackground (Void...arg0){
            if (connection.isConnected())
                return false;
            isconnecting = true;
            if (isToasted)
                new Handler(Looper.getMainLooper()).post(new Runnable() {

                    @Override
                    public void run() {

                        Toast.makeText(context, caller + "=>connecting....", Toast.LENGTH_LONG).show();
                    }
                });
            Log.e("Connect() Function", caller + "=&gt;connecting....");

            try {
                connection.setPacketReplyTimeout(20000);
                // Enable automatic reconnection
                connMgr = ReconnectionManager.getInstanceFor(connection);
                connMgr.enableAutomaticReconnection();
                connMgr.setFixedDelay(2);
                //connMgr.setDefaultFixedDelay(1);
                //connMgr.setReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.FIXED_DELAY);
                connection.connect();
                DeliveryReceiptManager dm = DeliveryReceiptManager
                        .getInstanceFor(connection);
                dm.setAutoReceiptMode(AutoReceiptMode.always);
                dm.addReceiptReceivedListener(new ReceiptReceivedListener() {

                    @Override
                    public void onReceiptReceived(final String fromid,
                                                  final String toid, final String msgid,
                                                  final Stanza packet) {

                    }
                });
                connected = true;
                MainActivity.fConn = true;
            } catch (IOException e) {
                if (isToasted)
                    new Handler(Looper.getMainLooper())
                            .post(new Runnable() {

                                @Override
                                public void run() {

                                    Toast.makeText(
                                            context,
                                            "(" + caller + ")"
                                                    + "IOException: ",
                                            Toast.LENGTH_SHORT).show();
                                }
                            });

                Log.e("(" + caller + ")", "IOException: " + e.getMessage());
            } catch (SmackException e) {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                      // Toast.makeText(context, "(" + caller + ")" + "SMACKException: ", Toast.LENGTH_SHORT).show();
                    }
                });
                Log.e("(" + caller + ")",
                        "SMACKException: " + e.getMessage());
                //mHandler.post(checkConn); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!<-- Problem place
                //instance = null;
                //MyService.getInstance().destroyService(); 
            } catch (XMPPException e) {
                if (isToasted)

                    new Handler(Looper.getMainLooper())
                            .post(new Runnable() {

                                @Override
                                public void run() {

                                    Toast.makeText(
                                            context,
                                            "(" + caller + ")"
                                                    + "XMPPException: ",
                                            Toast.LENGTH_SHORT).show();
                                }
                            });
                Log.e("connect(" + caller + ")",
                        "XMPPException: " + e.getMessage());

            }
            return isconnecting = false;
        }
    } ;
    connectionThread.execute();
}

public static void login() {
    try {
        Log.e(loginUser,passwordUser);
        loginUser = GlobalVariables.user_id;
        passwordUser = GlobalVariables.user_password;
        connection.login(loginUser, passwordUser);
        Log.e("LOGIN", "Yey! We're connected to the Xmpp server!");
        sendBufMessages();
        myRoster = Roster.getInstanceFor(connection);
        if (!myRoster.isLoaded()) {
            try{ myRoster.reloadAndWait(); }
            catch (Exception e) {System.out.println(e);}
        }
        myRoster.setDefaultSubscriptionMode(Roster.SubscriptionMode.accept_all);
        myRoster.addRosterListener(new RosterListener() {
            public void entriesAdded(Collection<String> addresses) {}
            public void entriesDeleted(Collection<String> addresses) {}
            public void entriesUpdated(Collection<String> addresses) {}
            public void presenceChanged(Presence presence) {
                Log.e("Roster","Presence changed: " + presence.getFrom() + " " + presence);
                String uname = presence.getFrom();
                int pos = uname.indexOf('@',0);
                uname = uname.substring(0,pos);
                Presence.Type ptype = presence.getType(); //Presence.type.available
                for(int i=0;i<stat_list.size();i++){
                    HashMap<String,String> item = new HashMap<String, String>();
                    item = stat_list.get(i);
                    if (uname.equals(item.get("user_id").toString())) { stat_list.remove(i); break;}
                }
                HashMap<String,String> item = new HashMap<>();
                item.put("user_id",uname);
                if (ptype == Presence.Type.available){ item.put("onl","true"); }
                if (ptype == Presence.Type.unavailable){ item.put("onl","false"); }
                stat_list.add(0,item);
                if (MainActivity.chatlist_selected) { ChatList.getInstance().startStatProc(); }
                if (GlobalVariables.onchat == true & GlobalVariables.vuser_id.equals(uname)){
                    if (ptype == Presence.Type.available) { Chat.setUserStatus("onl"); }
                    if (ptype == Presence.Type.unavailable) {Chat.setUserStatus("offl");}
                }
            }
        });
    } catch (XMPPException | SmackException | IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private class ChatManagerListenerImpl implements ChatManagerListener {
    @Override
    public void chatCreated(final org.jivesoftware.smack.chat.Chat chat,
                            final boolean createdLocally) {
        if (!createdLocally)
            chat.addMessageListener(mMessageListener);

    }

}

public void sendMessage(ChatMessage chatMessage) {
.....
}

public class XMPPConnectionListener implements ConnectionListener {
    @Override
    public void connected(final XMPPConnection connection) {

        Log.e("xmpp", "Connected!");
        connected = true;
        curr_delay = 0; connMgr.setFixedDelay(2);
            login();
    }

    @Override
    public void connectionClosed() {
        if (isToasted)

            new Handler(Looper.getMainLooper()).post(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub

                    Toast.makeText(context, "ConnectionCLosed!",
                            Toast.LENGTH_SHORT).show();

                }
            });
        Log.d("xmpp", "ConnectionCLosed!");
        connected = false;
        chat_created = false;
        loggedin = false;
    }

    @Override
    public void connectionClosedOnError(Exception arg0) {
        if (isToasted)
            new Handler(Looper.getMainLooper()).post(new Runnable() {

                @Override
                public void run() {
                    Toast.makeText(context, "ConnectionClosedOn Error!!",
                            Toast.LENGTH_SHORT).show();

                }
            });
        Log.e("xmpp", "ConnectionClosedOn Error!");
        connected = false;
        chat_created = false;
        loggedin = false;
    }

    @Override
    public void reconnectingIn(int arg0) {

        Log.e("xmpp", "Reconnectingin " + arg0);
        if (arg0==0 & curr_delay<5){
            curr_delay++;
            connMgr.setFixedDelay(rt_arr[curr_delay]);
        }
        loggedin = false;
    }

    @Override
    public void reconnectionFailed(Exception arg0) {
        if (isToasted)

            new Handler(Looper.getMainLooper()).post(new Runnable() {

                @Override
                public void run() {

                    Toast.makeText(context, "ReconnectionFailed!",
                            Toast.LENGTH_SHORT).show();

                }
            });
        Log.d("xmpp", "ReconnectionFailed!");
        connected = false;

        chat_created = false;
        loggedin = false;
    }

    @Override
    public void reconnectionSuccessful() {
        if (isToasted)

            new Handler(Looper.getMainLooper()).post(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub

                    Toast.makeText(context, "REConnected!",
                            Toast.LENGTH_SHORT).show();

                }
            });
        Log.d("xmpp", "ReconnectionSuccessful");
        curr_delay = 0; connMgr.setFixedDelay(2);
        connected = true;
        //MainActivity.fConn = true;
        chat_created = false;
        loggedin = false;
    }

    @Override
    public void authenticated(XMPPConnection arg0, boolean arg1) {
        Log.d("xmpp", "Authenticated!");
        loggedin = true;

        ChatManager.getInstanceFor(connection).addChatListener(
                mChatManagerListener);

        chat_created = false;
        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }).start();
        if (isToasted)

            new Handler(Looper.getMainLooper()).post(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub

                    Toast.makeText(context, "Connected!",Toast.LENGTH_SHORT).show();

                }
            });
    }
}

private class MMessageListener implements ChatMessageListener {

    @Override
    public void processMessage(final org.jivesoftware.smack.chat.Chat chat,
                               final Message message) {
        Log.i("MyXMPP_MESSAGE_LISTENER", "Xmpp message received: '"
                + message);

...
        }
    }



private Runnable checkConn = new Runnable() {
    public void run() {
        try {
            Socket socket = new Socket(host, 5222);
            socket.shutdownInput();
            socket.shutdownOutput();
            socket.close();
        } catch(Exception e){Log.e("Socket",e.toString());}
        disconnect();
        Log.e("MyXMPP","disconnect");
        mHandler.postDelayed(checkConn2,3000);
    }
};
private Runnable checkConn2 = new Runnable() {
    public void run() {
        connect("After SmackException");
    }
};


}

更新 26.09.17。经过几天的实验,我仍然没有找到解决办法。 我尝试使用前台服务、PingManager、broadcastreceiver 重新创建服务,但没有结果。现在我尝试在系统内存不足时向应用程序发送压力信号。 更新 05.10.17 我仍然没有找到解决方案。我在 Android 4.1.2 上测试了这个程序。它工作正常。在 Android 5.1.1 上,它在退出 activity 后工作了大约 3 分钟,然后我收到连接被拒绝的错误。当我从return到activity时,错误就消失了。在 Android 6.0.1 上类似情况,但错误略有不同 java.net.SocketTimeoutException:10000 毫秒后无法连接到 /94.130.25.242(端口 80)。我认为系统会在一段时间后在服务中阻止网络 activity,但不会在活动中阻止网络 (?)。

小米手机后台无法使用长网连接。一段时间后,MIUI 会阻止任何网络连接。对于关键网络连接,您可以使用 Firebase Cloud Messaging,它在 Android 系统中具有高优先级。它可以启动必要的后台作业。 它还可以通知用户有关传入的消息。收到此消息后,用户将点击它并 return 到他的 activity,xmpp 连接将恢复。

尝试在您的 AndroidManifest.xml

中添加权限
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND"/>
    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
    <uses-permission android:name="android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND"/>

并在您的服务中 onCreate() 下面编写代码。我希望它对某人有所帮助。

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            if (pm != null) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    Intent intent = new Intent();
                    String packageName = getPackageName();
                    if (!pm.isIgnoringBatteryOptimizations(packageName)) {
                        intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
                        intent.setData(Uri.parse("package:" + packageName));
                        startActivity(intent);
                    }
                }

                Log.d(TAG, "PowerManager.SCREEN_DIM_WAKE_LOCK+PowerManager.ON_AFTER_RELEASE");
                pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK + PowerManager.ON_AFTER_RELEASE, "wetwars:activityrecognition").acquire();
                pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "WetWars:WakeLockActivity").acquire();
            }