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!
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 客户端命名空间disconnect
apabila memutuskan sambungan.
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!