Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/192.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 安卓服务可以';t仅在节电模式下娱乐后连接服务器_Android_Sockets_Server_Kotlin_Connectexception - Fatal编程技术网

Android 安卓服务可以';t仅在节电模式下娱乐后连接服务器

Android 安卓服务可以';t仅在节电模式下娱乐后连接服务器,android,sockets,server,kotlin,connectexception,Android,Sockets,Server,Kotlin,Connectexception,我正在编写一个聊天应用程序,服务器和Android客户端都是用Kotlin编写的。我创建了一个后台服务,它不断地从连接到服务器的套接字读取消息,并在消息到达时发送通知。在用户点击“x”按钮并关闭应用程序之前,一切正常。在执行下面发布的清理代码期间,与服务器的连接失败。在服务管理发送退出请求并关闭流之前,服务器已获得EOF。然后,重新创建服务,但当它尝试连接到服务器时,它会收到ConnectException(连接被拒绝)。只有在启用电池节约模式时才会发生这种情况。当它关闭或手机连接到我的笔记本电

我正在编写一个聊天应用程序,服务器和Android客户端都是用Kotlin编写的。我创建了一个后台服务,它不断地从连接到服务器的套接字读取消息,并在消息到达时发送通知。在用户点击“x”按钮并关闭应用程序之前,一切正常。在执行下面发布的清理代码期间,与服务器的连接失败。在服务管理发送退出请求并关闭流之前,服务器已获得EOF。然后,重新创建服务,但当它尝试连接到服务器时,它会收到ConnectException(连接被拒绝)。只有在启用电池节约模式时才会发生这种情况。当它关闭或手机连接到我的笔记本电脑与USB和充电没有问题

ss命令列出指定端口上有人在侦听,因此这不是问题所在。我试着在一个循环中连接,我。E尝试每10秒连接5次,但每次都被拒绝。我试着在两个不同的端口上监听,但都失败了,即使其中一个以前没有使用过。文档中说默认的待办事项是50,所以我猜也不是这样。我试图在服务器套接字上设置一个SO_REUSEADDR标志,但仍然没有设置。奇怪的是,当我第二次启动应用程序时,它可以再次连接。因此,我创建了一个广播接收器,它以与应用程序相同的方式启动服务,以防应用程序崩溃,但也没有任何帮助

我真的在谷歌上搜索了一个多星期,但这是我第一次尝试同时使用Kotlin和sockets,我的想法已经没有了。如果有人对可能发生的事情有线索,我真的很感谢你的帮助

以下是服务启动命令:

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    activeConversation = intent?.getStringExtra(CONV_NAME) ?: ""
    login = intent?.getStringExtra(LOGIN) ?: login
    if (thread?.isAlive != true) {
        thread = thread(start = true) {
                synchronized(lock) {
                    try {
                        socket = Socket(SERVER_IP, SERVICE_PORT)
                        output = ObjectOutputStream(socket?.getOutputStream())
                        input = ObjectInputStream(socket?.getInputStream())
                        output?.writeObject(Request(START_SERVICE, mutableMapOf(LOGIN to login)))
                    } catch (e: IOException) {
                        e.printStackTrace()
                        return@thread
                    }
                }
                handleMessages() //contains input?.readObject() in infinite loop
        }
    }
    return START_STICKY
}
在onDestory()和onTaskRemoved()中,我调用此函数:

 private fun cleanUp() {
    synchronized(lock) {
        thread(start = true) {
            try {
                output?.writeObject(Request(EXIT, mutableMapOf(LOGIN to login)))
                output?.close()
                input?.close()
                socket?.close()
                nullStreams()
                thread?.join()
                println("SERVICE: thread joined")
            } catch(e: IOException) {
                e.printStackTrace()
                return@thread
            } finally {
                println("Service sends broadcast to ask for recreation")
                val restartIntent = Intent(this, ServiceRestarter::class.java)
                restartIntent.putExtra(LOGIN, login)
                sendBroadcast(restartIntent)
            }
        }.join()
    }
}
服务重新启动程序:

class ServiceRestarter : BroadcastReceiver() {

override fun onReceive(context: Context, intent: Intent?) {
    val login = intent?.getStringExtra(LOGIN)
    println("SERVICE RESTARTER: receiving restart request from $login")
    val serviceIntent = Intent(context, MessengerService::class.java)
    serviceIntent.putExtra(LOGIN, login)
    context.startService(serviceIntent)
}}
我的服务器中负责侦听的部分:

val clientsSocket = ServerSocket(CLIENTS_PORT)
    val serviceSocket = ServerSocket(SERVICE_PORT)
    serviceSocket.setReuseAddress(true)
    println("Server socket ready!")
    println("Service socket port: ${serviceSocket.localPort}")

    thread(start = true) {
            while(true) ClientThread(clientsSocket.accept(), loggedInUsers, pendingRequests).start()
    }
    thread(start = true) {
            while(true) ServiceThread(serviceSocket.accept(), loggedInUsers).start()
    }
和ServiceThread:

class ServiceThread(val socket: Socket, 
    val loggedInUsers: HashMap<String, UserConnection>) : Thread() {

private var login = ""
private val input = ObjectInputStream(socket.getInputStream())
private val output = ObjectOutputStream(socket.getOutputStream())

override fun run() {

    var request = input.readObject() as Request
    login = request.content[LOGIN] as String 
    var userConn: UserConnection?
    synchronized(loggedInUsers) {
        userConn = loggedInUsers[login]
        if(request.action == START_SERVICE) {
            println("SERVICE THREAD: New socket conn from $login")
            userConn?.run {
                println("SERVICE THREAD: putting $login output to logged in users")
                serviceStream = output
                if(pendingMessage != null) {
                    output.writeObject(Request(SEND,
                        mutableMapOf(RESULT to SUCCESS, DATA to pendingMessage)))
                    pendingMessage = null
                }
            }
        }
    }
    try { request = input.readObject() as Request }
    catch(e: IOException) {
        println(e.printStackTrace())
        cleanUp()
        return@run
    }
    if(request.action == EXIT) { 
        println("SERVICE THREAD: Service of user $login is terminating")
        cleanUp()
    }
}

private fun cleanUp() {

    synchronized(loggedInUsers) { 
        output.close()
        input.close()
        socket.close()
        loggedInUsers[login]?.serviceStream = null
    }
}}
class-ServiceThread(val-socket:socket,
val loggedInUsers:HashMap):Thread(){
private var login=“”
private val input=ObjectInputStream(socket.getInputStream())
private val output=ObjectOutputStream(socket.getOutputStream())
覆盖趣味跑(){
var request=input.readObject()作为请求
login=request.content[login]作为字符串
var userConn:UserConnection?
已同步(loggedInUsers){
userConn=loggedInUsers[login]
if(request.action==启动服务){
println(“服务线程:来自$login的新套接字连接”)
用户控制?运行{
println(“服务线程:将$login输出放入登录用户”)
服务流=输出
如果(pendingMessage!=null){
output.writeObject(请求(发送、,
mutableMapOf(结果到成功,数据到pendingMessage)))
pendingMessage=null
}
}
}
}
尝试{request=input.readObject()作为请求}
捕获(e:IOException){
println(例如printStackTrace())
清理()
return@run
}
如果(request.action==EXIT){
println(“服务线程:用户$login的服务正在终止”)
清理()
}
}
私人娱乐清理(){
已同步(loggedInUsers){
output.close()
input.close()
socket.close()
loggedInUsers[登录]?.serviceStream=null
}
}}

您是否尝试过作业调度程序?这是安卓的建议,看看这里:对于打瞌睡的状态谢谢,我会试试看。而且我忘了提到。如果你想让你的应用程序在服务被关闭后仍能继续运行,你可能需要查看
ForegroundService
。也许这有帮助