Maison >développement back-end >Golang >L'application Android ne peut pas se connecter au serveur socket.io Golang

L'application Android ne peut pas se connecter au serveur socket.io Golang

PHPz
PHPzavant
2024-02-08 21:48:221169parcourir

Android应用程序无法连接到socket.io Golang服务器

最近,一些Android应用程序无法连接到socket.io Golang服务器的问题引起了广泛关注。php小编新一在此为大家解答。在使用socket.io Golang服务器时,有一些常见的连接问题可能导致Android应用程序无法连接。首先,确保你的Android应用程序和服务器在相同的网络环境下,并且能够互相访问。另外,检查你的代码中是否正确设置了服务器的地址和端口。如果问题仍然存在,可以尝试使用其他网络调试工具来检查连接问题,如Wireshark等。希望这些解答能帮助到你解决问题!

问题内容

我不知道我是否遗漏了一些东西,因为我的 kotlin 代码没有找到 golang 套接字服务器。我做了一个 netstat -ano 并且端口 8000 已经用于 tcp,所以我认为套接字服务器运行良好。但我的安卓还是找不到。服务器和模拟器都在同一网络上。这是我的代码:

//服务器(golang)

import (
    "fmt"
    "net/http"

    socketio "github.com/googollee/go-socket.io"
    "github.com/googollee/go-socket.io/engineio"
    "github.com/googollee/go-socket.io/engineio/transport"
    "github.com/googollee/go-socket.io/engineio/transport/polling"
    "github.com/googollee/go-socket.io/engineio/transport/websocket"
)

server := socketio.newserver(&engineio.options{
    transports: []transport.transport{
        &polling.transport{
            checkorigin: alloworiginfunc,
        },
        &websocket.transport{
            checkorigin: alloworiginfunc,
        },
    },
})

server.onconnect("/", func(s socketio.conn) error {
    s.setcontext("")
    fmt.println("connected:", s.id())
    return nil
})

server.onevent("/", "notice", func(s socketio.conn, msg string) {
    fmt.println("notice:", msg)
    s.emit("reply", "have "+msg)
})

server.onerror("/", func(s socketio.conn, e error) {
    fmt.println("meet error:", e)
})

server.ondisconnect("/", func(s socketio.conn, reason string) {
    fmt.println("closed", reason)
})

go server.serve()
defer server.close()

http.handle("/socket.io/", server)
http.handle("/", http.fileserver(http.dir("./asset")))

fmt.println("scktsrv serving at localhost:8000...")
fmt.print(http.listenandserve(":8000", nil))

//android(kotlin)

<uses-permission android:name="android.permission.internet" />

implementation ('io.socket:socket.io-client:2.0.0') {
    exclude group: 'org.json', module: 'json'
}

try {
    msocket = io.socket("http://localhost:8000/skt")
    log.d(tag, "success: ${msocket.id()}")
} catch (e: exception) {
    e.localizedmessage?.let { log.e(tag, it) }
}

msocket.connect()
msocket.on(socket.event_connect, onconnect)
msocket.on("reply", onreply)

private var onconnect = emitter.listener {
    log.i(tag, "onconnect")
    msocket.emit("notice", "{\"relay_num\": 4, \"to_status\": 1}")
}

private var onreply = emitter.listener {
    log.i(tag, "replymsg: ${it[0]}")
}

更新:

在@dev.bmax的回答之前,我已经发现了一些关于启用cleartexttraffic的信息,并且已经在我的androidmanifest.xml上添加了 android:usescleartexttraffic="true" ,但该应用程序仍然无法连接到服务器。 socket.connected() 现在返回 false。

另外,您应该如何实际连接到服务器?我只需要 http://10.0.2.2:8000 而不需要任何路径吗?

更新:

我刚刚注意到我不断收到如下所示的日志:

tagsocket(6) with statstag=0xffffffff, statsuid=-1

它不断在 logcat 上弹出

更新:

我四处寻找其他代码,并找到了一个可以工作的代码。幸运或不幸的是,这很简单。这是我找到的代码:

//go语言

listener, _ := net.listen("tcp", ":8000")
for {
    conn, _ := listener.accept()
    fmt.printf("%s --- %s\n", conn.localaddr(), conn.remoteaddr())
    io.writestring(conn, "welcome to socket")
}

//android kotlin

val host = "192.168.100.250"
val port = 8000

executors.newsinglethreadexecutor().execute {
    try {
        val socket = java.net.socket(host, port)
        receivemove(socket)
    } catch (e: connectexception) {
        log.e(tag, "socket connexc: ${e.localizedmessage}")
        runonuithread {
            toast.maketext(this, "connection failed", toast.length_short).show()
        }
    }catch (e: exception) {
        log.e(tag, "socket connexc: ${e.localizedmessage}")
    }
}

现在我想知道,为什么准系统代码可以工作,而 googollee 库提供的代码却不能?我认为我没有错过双方的任何设置。

更新:

取得了一些进展。发现 android 代码可以工作,但由于某种原因正在执行一些意外的问题。以下是我在 android 端所做的更改的详细信息:

// 应用程序 build.gradle

implementation('io.socket:socket.io-client:0.8.3') {
    exclude group: 'org.json', module: 'json'
}

//mainactivity.kt

import io.socket.client.io
import io.socket.client.socket

init {
    try {
        msocket = io.socket("http://<local_ip>:8000/socket.io/")
    }catch (e: connectexception) {
        log.e(tag, "socket connexc: ${e.localizedmessage}")
    }catch (e: urisyntaxexception) {
        log.e(tag, "socket urisynexc: ${e.localizedmessage}")
    }catch (e: exception){
        log.e(tag, "socket exc: ${e.localizedmessage}")
    }
}

// androidmanifest.xml

android:usesCleartextTraffic="true"
//I used to have android:networkSecurityConfig="@xml/network_security_config" here as well

完成这些更改后,应用程序现在可以连接到服务器。但连接后,应用程序似乎立即断开连接。然后它再次连接到服务器,然后再次断开连接,然后连接到服务器,这个循环似乎没有停止。我在断开连接时收到 lated 客户端命名空间dis​​connect

解决方法

我终于找到了使这项工作发挥作用的部分。我认为最大的问题是在android方面。更换要使用的库似乎已经解决了所有问题,然后只需进行一个小的更改即可解决立即断开连接的问题。以下是双方的最终代码和其他详细信息:

//go语言

package main

import (
    "fmt"
    "net/http"

    socketio "github.com/googollee/go-socket.io"
    "github.com/googollee/go-socket.io/engineio"
    "github.com/googollee/go-socket.io/engineio/transport"
    "github.com/googollee/go-socket.io/engineio/transport/polling"
    "github.com/googollee/go-socket.io/engineio/transport/websocket"
)

var alloworiginfunc = func(r *http.request) bool {
    return true
}

func main() {
    server := socketio.newserver(&engineio.options{
        transports: []transport.transport{
            &polling.transport{
                checkorigin: alloworiginfunc,
            },
            &websocket.transport{
                checkorigin: alloworiginfunc,
            },
        },
    })

    server.onconnect("/", func(s socketio.conn) error {
        s.setcontext("")
        fmt.println("connected:", s.id())
        return nil
    })

    server.onevent("/", "notice", func(s socketio.conn, msg string) {
        fmt.println("notice:", msg)
        s.emit("reply", "have "+msg)
    })

    server.onerror("/", func(s socketio.conn, e error) {
        fmt.println("error:", e)
    })

    server.ondisconnect("/", func(s socketio.conn, reason string) {
        fmt.println("closed", reason)
    })

    go server.serve()
    defer server.close()

    http.handle("/socket.io/", server)
    http.handle("/", http.fileserver(http.dir("./asset")))

    fmt.println("socket server serving at localhost:8000...")
    fmt.print(http.listenandserve(":8000", nil))
}

// 安卓 kotlin

androidmanifest.xml

<uses-permission android:name="android.permission.internet" />

<application
    ...
    android:usescleartexttraffic="true">

应用程序构建.gradle

implementation('io.socket:socket.io-client:0.8.3') {
        exclude group: 'org.json', module: 'json'
    }

// mainactivity.kt 或任何您想放置此内容的地方

import io.socket.client.IO
import io.socket.client.Socket

class MainActivity : AppCompatActivity() {
    private lateinit var mSocket: Socket
    ...
    
    init {
        try {
            mSocket = IO.socket("http://<host>:8000/")
        }catch (e: ConnectException) {
            Log.e(TAG, "Socket ConnExc: ${e.localizedMessage}")
        }catch (e: URISyntaxException) {
            Log.e(TAG, "Socket URISynExc: ${e.localizedMessage}")
        }catch (e: Exception){
            Log.e(TAG, "Socket Exc: ${e.localizedMessage}")
        }
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        mSocket.connect()
        
        binding.btnSend.setOnClickListener {
            Log.i(TAG, "isConnected: ${mSocket.connected()}")
            mSocket.emit("notice", "from_app_msg")
        }
    }
    
    override fun onDestroy() {
        super.onDestroy()

        mSocket.off()
        mSocket.disconnect()
    }
}

关于立即断开,看起来你在android端尝试连接时并不需要添加/socket.io。删除它解决了断开连接的问题。而且您的项目中不需要 asset 文件夹。伙计,这个 socket.io 东西很奇怪。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer