Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Aplikasi Android tidak boleh menyambung ke pelayan socket.io Golang

Aplikasi Android tidak boleh menyambung ke pelayan socket.io Golang

PHPz
PHPzke hadapan
2024-02-08 21:48:221098semak imbas

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

Baru-baru ini, masalah beberapa aplikasi Android tidak dapat disambungkan ke pelayan socket.io Golang telah menarik perhatian meluas. Editor PHP Xinyi berada di sini untuk menjawab soalan untuk semua orang. Apabila menggunakan pelayan socket.io Golang, terdapat beberapa isu sambungan biasa yang boleh menyebabkan aplikasi Android gagal disambungkan. Mula-mula, pastikan aplikasi dan pelayan Android anda berada pada persekitaran rangkaian yang sama dan boleh mengakses satu sama lain. Juga, semak bahawa alamat dan port pelayan ditetapkan dengan betul dalam kod anda. Jika masalah berterusan, anda boleh cuba menggunakan alat penyahpepijatan rangkaian lain untuk menyemak isu sambungan, seperti Wireshark, dsb. Harap jawapan ini dapat membantu anda menyelesaikan masalah anda!

Kandungan soalan

Saya tidak tahu sama ada saya kehilangan sesuatu, kerana kotlin 代码没有找到 golang 套接字服务器。我做了一个 netstat -ano dan port 8000 saya sudah digunakan untuk tcp, jadi saya menganggap pelayan soket berfungsi dengan baik. Tetapi Android saya masih tidak menemuinya. Kedua-dua pelayan dan emulator berada pada rangkaian yang sama. Ini kod saya:

//Pelayan (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]}")
}

Kemas kini:

Sebelum jawapan @dev.bmax, saya telah menemui beberapa maklumat tentang mendayakan cleartexttraffic dan sudah ada dalam saya androidmanifest.xml上添加了 android:usescleartexttraffic="true" ,但该应用程序仍然无法连接到服务器。 socket.connected() kini mengembalikan palsu.

Selain itu, bagaimanakah anda sepatutnya menyambung ke pelayan? Adakah saya hanya perlukan http://10.0.2.2:8000 tanpa sebarang laluan?

Kemas kini:

Saya baru perasan bahawa saya terus mendapat log seperti ini:

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

Ia terus muncul di logcat

Kemas kini:

Saya melihat sekeliling untuk mencari kod lain dan mendapati kod yang berfungsi. Nasib baik atau malangnya, ia agak mudah. Ini kod yang saya jumpa:

//go language

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}")
    }
}

Sekarang saya tertanya-tanya, mengapa kod barebones berfungsi tetapi kod yang disediakan oleh perpustakaan googollee tidak berfungsi? Saya tidak fikir saya terlepas sebarang persediaan di kedua-dua belah pihak.

Kemas kini:

Beberapa kemajuan telah dicapai. Ditemui android Kod berfungsi tetapi atas sebab tertentu sedang melaksanakan beberapa isu yang tidak dijangka. Berikut adalah butiran perubahan yang saya buat pada bahagian android:

// binaan aplikasi.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

Selepas melengkapkan perubahan ini, aplikasi kini boleh menyambung ke pelayan. Tetapi selepas menyambung, apl itu nampaknya terputus sambungan serta-merta. Kemudian ia menyambung ke pelayan sekali lagi, kemudian memutuskan sambungan lagi, kemudian menyambung ke pelayan, dan kitaran nampaknya tidak berhenti. Saya mendapat lated 客户端命名空间dis​​connect apabila memutuskan sambungan.

Penyelesaian

Saya akhirnya menemui bahagian yang membuat ini berfungsi. Saya fikir masalah terbesar adalah pada bahagian android. Menukar pustaka untuk digunakan nampaknya telah membetulkan semua isu, dan kemudian hanya perubahan kecil menyelesaikan isu putus sambungan serta-merta. Berikut ialah kod akhir dan butiran lain daripada kedua-dua pihak:

//go language

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))
}

// Android kotlin

androidmanifest.xml

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

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

app-build.gradle

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

// mainactivity.kt atau di mana sahaja anda nak letak kandungan ini

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()
    }
}

Berkenaan putus sambungan serta-merta, nampaknya anda tidak perlu menambah /socket.io。删除它解决了断开连接的问题。而且您的项目中不需要 asset 文件夹。伙计,这个 socket.io apabila cuba menyambung di bahagian android.

Atas ialah kandungan terperinci Aplikasi Android tidak boleh menyambung ke pelayan socket.io Golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam