Android应用无法连接到socket.io的Golang服务器。

huangapple go评论139阅读模式
英文:

Android app can't connect to socket.io Golang server

问题

我不知道是否有什么遗漏,因为我的Kotlin代码找不到Golang的socket服务器。我执行了netstat -ano命令,发现端口8000已经被TCP占用,所以我认为socket服务器正常运行。但是我的Android设备仍然无法找到它。服务器和模拟器都在同一个网络上。以下是我的代码:

// 服务器(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的回答之前,我已经发现了关于启用明文流量的一些内容,并已经在我的AndroidManifest.xml中添加了android:usesCleartextTraffic="true",但是应用程序仍然无法连接到服务器。Socket.connected()现在返回false。

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

更新:

我刚刚注意到我一直在收到以下日志:

tagSocket(6) with statsTag=0xffffffff, statsUid=-1

它一直在logcat中不断出现。

更新:

我找到了其他代码,并找到了一个可行的代码。幸运或不幸的是,它非常简单。以下是我找到的代码:

// Golang

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端所做更改的详细信息:

// app 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"
// 我之前在这里还有android:networkSecurityConfig="@xml/network_security_config"

通过这些更改,应用程序现在可以连接到服务器。但是在连接后立即断开连接,然后再次连接到服务器,然后再次断开连接,这个循环似乎没有停止。在断开连接时,我得到了closed client namespace disconnect的错误消息。

英文:

I don't know if I'm missing something, because my Kotlin code isn't finding the Golang socket server. I did a netstat -ano and the port 8000 was being used for TCP already so I think the socket server is running fine. But my android still can't find it. Both the server and the emulator is on the same network. Here's my code:

//server(Golang)

import (
	&quot;fmt&quot;
	&quot;net/http&quot;

	socketio &quot;github.com/googollee/go-socket.io&quot;
	&quot;github.com/googollee/go-socket.io/engineio&quot;
	&quot;github.com/googollee/go-socket.io/engineio/transport&quot;
	&quot;github.com/googollee/go-socket.io/engineio/transport/polling&quot;
	&quot;github.com/googollee/go-socket.io/engineio/transport/websocket&quot;
)

server := socketio.NewServer(&amp;engineio.Options{
	Transports: []transport.Transport{
		&amp;polling.Transport{
			CheckOrigin: allowOriginFunc,
		},
		&amp;websocket.Transport{
			CheckOrigin: allowOriginFunc,
		},
	},
})

server.OnConnect(&quot;/&quot;, func(s socketio.Conn) error {
	s.SetContext(&quot;&quot;)
	fmt.Println(&quot;connected:&quot;, s.ID())
	return nil
})

server.OnEvent(&quot;/&quot;, &quot;notice&quot;, func(s socketio.Conn, msg string) {
	fmt.Println(&quot;notice:&quot;, msg)
	s.Emit(&quot;reply&quot;, &quot;have &quot;+msg)
})

server.OnError(&quot;/&quot;, func(s socketio.Conn, e error) {
	fmt.Println(&quot;meet error:&quot;, e)
})

server.OnDisconnect(&quot;/&quot;, func(s socketio.Conn, reason string) {
	fmt.Println(&quot;closed&quot;, reason)
})

go server.Serve()
defer server.Close()

http.Handle(&quot;/socket.io/&quot;, server)
http.Handle(&quot;/&quot;, http.FileServer(http.Dir(&quot;./asset&quot;)))

fmt.Println(&quot;ScktSrv Serving at localhost:8000...&quot;)
fmt.Print(http.ListenAndServe(&quot;:8000&quot;, nil))

//android(Kotlin)

&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt;

implementation (&#39;io.socket:socket.io-client:2.0.0&#39;) {
	exclude group: &#39;org.json&#39;, module: &#39;json&#39;
}

try {
	mSocket = IO.socket(&quot;http://localhost:8000/skt&quot;)
	Log.d(TAG, &quot;success: ${mSocket.id()}&quot;)
} catch (e: Exception) {
	e.localizedMessage?.let { Log.e(TAG, it) }
}

mSocket.connect()
mSocket.on(Socket.EVENT_CONNECT, onConnect)
mSocket.on(&quot;reply&quot;, onReply)

private var onConnect = Emitter.Listener {
	Log.i(TAG, &quot;onConnect&quot;)
	mSocket.emit(&quot;notice&quot;, &quot;{\&quot;relay_num\&quot;: 4, \&quot;to_status\&quot;: 1}&quot;)
}

private var onReply = Emitter.Listener {
	Log.i(TAG, &quot;replyMsg: ${it[0]}&quot;)
}

UPDATE:

Before @dev.bmax's answer, I already found out something about enabling cleartexttraffic and already added android:usesCleartextTraffic=&quot;true&quot; on my AndroidManifest.xml, but the app still can't connect to the server. Socket.connected() returns false right now.

Also, how should you actually connect to the server? Do I just need http://10.0.2.2:8000 without any path?

UPDATE:

I just noticed that I keep getting a log that looks like this:

tagSocket(6) with statsTag=0xffffffff, statsUid=-1

And it keeps popping up on the logcat

UPDATE:

I looked around for other code, and I found a working one. Which fortunately or unfortunately, is quite simple. Here's the codes I found:

//Golang

listener, _ := net.Listen(&quot;tcp&quot;, &quot;:8000&quot;)
for {
	conn, _ := listener.Accept()
	fmt.Printf(&quot;%s --- %s\n&quot;, conn.LocalAddr(), conn.RemoteAddr())
	io.WriteString(conn, &quot;welcome to socket&quot;)
}

//Android Kotlin

val host = &quot;192.168.100.250&quot;
val port = 8000

Executors.newSingleThreadExecutor().execute {
    try {
        val socket = java.net.Socket(host, port)
        receiveMove(socket)
    } catch (e: ConnectException) {
        Log.e(TAG, &quot;Socket ConnExc: ${e.localizedMessage}&quot;)
        runOnUiThread {
            Toast.makeText(this, &quot;connection failed&quot;, Toast.LENGTH_SHORT).show()
        }
    }catch (e: Exception) {
        Log.e(TAG, &quot;Socket ConnExc: ${e.localizedMessage}&quot;)
    }
}

Now I'm wondering, why does that barebones code work and the one provided by googollee library doesn't? I don't think I missed any settings for both sides.

UPDATE:

Got some progress. Found an android code that works, but for some reason is doing some unexpected issue. Here's the details of the change I made on the android side:

// app build.gradle

implementation(&#39;io.socket:socket.io-client:0.8.3&#39;) {
	exclude group: &#39;org.json&#39;, module: &#39;json&#39;
}

// MainActivity.kt

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

init {
	try {
		mSocket = IO.socket(&quot;http://&lt;local_IP&gt;:8000/socket.io/&quot;)
	}catch (e: ConnectException) {
		Log.e(TAG, &quot;Socket ConnExc: ${e.localizedMessage}&quot;)
	}catch (e: URISyntaxException) {
		Log.e(TAG, &quot;Socket URISynExc: ${e.localizedMessage}&quot;)
	}catch (e: Exception){
		Log.e(TAG, &quot;Socket Exc: ${e.localizedMessage}&quot;)
	}
}

// AndroidManifest.xml

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

With those changes, the app connects to the server now. But immediately after connecting, the app seems to get disconnected. Then it connects to the server again, then gets disconnected again, then connects to the server, and this cycle doesn't seem to stop. I'm getting a closed client namespace disconnect on the disconnects.

答案1

得分: 1

没有看到日志和错误消息,很难确定问题所在。除了错误的IP地址或端口号之外,可能的原因之一是使用明文连接(HTTP而不是HTTPS)。请注意,从Android 9(API级别28)开始,默认情况下禁用了明文支持。

您可以尝试使用安全连接(HTTPS)或在AndroidManifest中使用android:networkSecurityConfig属性启用明文流量。更多信息可以在文档中找到。

英文:

It's hard to identify the problem without seeing the logs, error messages.
One thing that could be the reason (besides an incorrect IP address or port number) is using cleartext connection (HTTP instead of HTTPS). Note that starting with Android 9 (API level 28), cleartext support is disabled by default.

You can try to either use a secure connection (HTTPS) or enable cleartext traffic in the AndroidManifest using the android:networkSecurityConfig attribute. More information can be found in the docs.

答案2

得分: 1

client namespace disconnect错误是由于在golang代码中未定义命名空间(URL路径)/skt导致的。

以下是示例代码:

package main

import (
	"log"
	"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"
)

// 更容易使用CORS。感谢@Vindexus和@erkie的帮助
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("")
		log.Println("connected:", s.ID())
		return nil
	})

	server.OnEvent("/", "notice", func(s socketio.Conn, msg string) {
		log.Println("notice:", msg)
		s.Emit("reply", "have "+msg)
	})

	server.OnError("/", func(s socketio.Conn, e error) {
		log.Println("meet error:", e)
	})

	// 我添加了一个新的端点skt
	// 注释掉这一段代码并刷新HTML页面
	// 将显示`closed client namespace disconnect`
	{
		server.OnConnect("/skt", func(s socketio.Conn) error {
			s.SetContext("")
			log.Println("connected:", s.ID())
			return nil
		})

		server.OnEvent("/skt", "notice", func(s socketio.Conn, msg string) {
			log.Println("notice:", msg)
			s.Emit("reply", "have [SKT]"+msg)
		})
	}

	server.OnDisconnect("/", func(s socketio.Conn, reason string) {
		log.Println("closed", reason)
	})

	go func() {
		if err := server.Serve(); err != nil {
			log.Fatalf("socketio listen error: %s\n", err)
		}
	}()
	defer server.Close()

	http.Handle("/socket.io/", server)
	http.Handle("/", http.FileServer(http.Dir("../asset")))

	log.Println("Serving at localhost:8000...")
	log.Fatal(http.ListenAndServe(":8000", nil))
}

以下是示例socket连接的HTML代码:

<!doctype html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
    <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
    <script src="https://code.jquery.com/jquery-1.11.1.js"></script>
    <script>
      var socket = io("http://localhost:8000/skt");
    //   var socket = io("http://localhost:8000"); you can try like this as well

      socket.on('reply', function(msg){
        $('#messages').append($('<li>').text(msg));
      });

      $('form').submit(function(){
        socket.emit('notice', $('#m').val());
        $('#m').val('');
        return false;
      });
    </script>
  </body>
</html>

希望这能帮助你解决问题。

英文:

The client namespace disconnect error receiving due to the namespace (url path) /skt is not defined in the golang code.

See the sample

package main
import (
&quot;log&quot;
&quot;net/http&quot;
socketio &quot;github.com/googollee/go-socket.io&quot;
&quot;github.com/googollee/go-socket.io/engineio&quot;
&quot;github.com/googollee/go-socket.io/engineio/transport&quot;
&quot;github.com/googollee/go-socket.io/engineio/transport/polling&quot;
&quot;github.com/googollee/go-socket.io/engineio/transport/websocket&quot;
)
// Easier to get running with CORS. Thanks for help @Vindexus and @erkie
var allowOriginFunc = func(r *http.Request) bool {
return true
}
func main() {
server := socketio.NewServer(&amp;engineio.Options{
Transports: []transport.Transport{
&amp;polling.Transport{
CheckOrigin: allowOriginFunc,
},
&amp;websocket.Transport{
CheckOrigin: allowOriginFunc,
},
},
})
server.OnConnect(&quot;/&quot;, func(s socketio.Conn) error {
s.SetContext(&quot;&quot;)
log.Println(&quot;connected:&quot;, s.ID())
return nil
})
server.OnEvent(&quot;/&quot;, &quot;notice&quot;, func(s socketio.Conn, msg string) {
log.Println(&quot;notice:&quot;, msg)
s.Emit(&quot;reply&quot;, &quot;have &quot;+msg)
})
server.OnError(&quot;/&quot;, func(s socketio.Conn, e error) {
log.Println(&quot;meet error:&quot;, e)
})
// I&#39;ve added a new endpoint skt
// Comment this block of code and refresh the htmt page
// and this will show `closed client namespace disconnect`
{
server.OnConnect(&quot;/skt&quot;, func(s socketio.Conn) error {
s.SetContext(&quot;&quot;)
log.Println(&quot;connected:&quot;, s.ID())
return nil
})
server.OnEvent(&quot;/skt&quot;, &quot;notice&quot;, func(s socketio.Conn, msg string) {
log.Println(&quot;notice:&quot;, msg)
s.Emit(&quot;reply&quot;, &quot;have [SKT]&quot;+msg)
})
}
server.OnDisconnect(&quot;/&quot;, func(s socketio.Conn, reason string) {
log.Println(&quot;closed&quot;, reason)
})
go func() {
if err := server.Serve(); err != nil {
log.Fatalf(&quot;socketio listen error: %s\n&quot;, err)
}
}()
defer server.Close()
http.Handle(&quot;/socket.io/&quot;, server)
http.Handle(&quot;/&quot;, http.FileServer(http.Dir(&quot;../asset&quot;)))
log.Println(&quot;Serving at localhost:8000...&quot;)
log.Fatal(http.ListenAndServe(&quot;:8000&quot;, nil))
}

and here is a sample socket connection html

&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Socket.IO chat&lt;/title&gt;
&lt;style&gt;
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages li { padding: 5px 10px; }
#messages li:nth-child(odd) { background: #eee; }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;ul id=&quot;messages&quot;&gt;&lt;/ul&gt;
&lt;form action=&quot;&quot;&gt;
&lt;input id=&quot;m&quot; autocomplete=&quot;off&quot; /&gt;&lt;button&gt;Send&lt;/button&gt;
&lt;/form&gt;
&lt;script src=&quot;https://cdn.socket.io/socket.io-1.2.0.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://code.jquery.com/jquery-1.11.1.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
var socket = io(&quot;http://localhost:8000/skt&quot;);
//   var socket = io(&quot;http://localhost:8000&quot;); you can try like this as well
socket.on(&#39;reply&#39;, function(msg){
$(&#39;#messages&#39;).append($(&#39;&lt;li&gt;&#39;).text(msg));
});
$(&#39;form&#39;).submit(function(){
socket.emit(&#39;notice&#39;, $(&#39;#m&#39;).val());
$(&#39;#m&#39;).val(&#39;&#39;);
return false;
});
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

hope this will helps you to resolve your problem

答案3

得分: 1

如果我正确理解你的代码,你应该尝试连接到 http://localhost:8000/socket.io/ 或者在 Android 应用中使用 127.0.0.1,因为你在 Go 服务器上为 SocketIO 提供了 /socket.io 端点。

英文:

If I understand your code correctly, you should try connecting to http://localhost:8000/socket.io/ or using 127.0.0.1 with the Android app, because you are serving in the Go server the /socket.io endpoint for SocketIO.

答案4

得分: 1

我终于找到了使这个工作正常的代码片段。我认为最大的问题在于安卓端。替换使用的库似乎修复了所有问题,然后只需进行一次小的更改以修复立即断开连接的问题。以下是双方的最终代码和其他详细信息:

// Golang

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 或者你想放置这段代码的任何位置

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

关于立即断开连接的问题,似乎在安卓端连接时不需要添加/socket.io。移除这部分修复了断开连接的问题。而且你的项目中不需要一个asset文件夹。嗨,这个socket.io的东西真奇怪。

英文:

I finally found the bits to make this work. I think the biggest issue was on the android side. Replacing the library to use seemed to have fixed all the issue, then just a minor change to fix the immediate disconnection issue. Here's the final code and additional details for both side:

// Golang

package main
import (
&quot;fmt&quot;
&quot;net/http&quot;
socketio &quot;github.com/googollee/go-socket.io&quot;
&quot;github.com/googollee/go-socket.io/engineio&quot;
&quot;github.com/googollee/go-socket.io/engineio/transport&quot;
&quot;github.com/googollee/go-socket.io/engineio/transport/polling&quot;
&quot;github.com/googollee/go-socket.io/engineio/transport/websocket&quot;
)
var allowOriginFunc = func(r *http.Request) bool {
return true
}
func main() {
server := socketio.NewServer(&amp;engineio.Options{
Transports: []transport.Transport{
&amp;polling.Transport{
CheckOrigin: allowOriginFunc,
},
&amp;websocket.Transport{
CheckOrigin: allowOriginFunc,
},
},
})
server.OnConnect(&quot;/&quot;, func(s socketio.Conn) error {
s.SetContext(&quot;&quot;)
fmt.Println(&quot;connected:&quot;, s.ID())
return nil
})
server.OnEvent(&quot;/&quot;, &quot;notice&quot;, func(s socketio.Conn, msg string) {
fmt.Println(&quot;notice:&quot;, msg)
s.Emit(&quot;reply&quot;, &quot;have &quot;+msg)
})
server.OnError(&quot;/&quot;, func(s socketio.Conn, e error) {
fmt.Println(&quot;error:&quot;, e)
})
server.OnDisconnect(&quot;/&quot;, func(s socketio.Conn, reason string) {
fmt.Println(&quot;closed&quot;, reason)
})
go server.Serve()
defer server.Close()
http.Handle(&quot;/socket.io/&quot;, server)
http.Handle(&quot;/&quot;, http.FileServer(http.Dir(&quot;./asset&quot;)))
fmt.Println(&quot;Socket server serving at localhost:8000...&quot;)
fmt.Print(http.ListenAndServe(&quot;:8000&quot;, nil))
}

// android kotlin

AndroidManifest.xml

&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt;
&lt;application
...
android:usesCleartextTraffic=&quot;true&quot;&gt;

app build.gradle

implementation(&#39;io.socket:socket.io-client:0.8.3&#39;) {
	exclude group: &#39;org.json&#39;, module: &#39;json&#39;
}

// MainActivity.kt or wherever you want to put this

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

About the immediate disconnection, it seems like you don't really need to add /socket.io when trying to connect on the android side. Removing that fixed the disconnection issue. And you don't need an asset folder on your project. Man, this socket.io thing is weird.

答案5

得分: 0

在尝试使用自己的客户端访问服务器之前,可以尝试使用CLI工具或浏览器访问。

以下是使用cURL的方法:

curl -i -X GET http://0.0.0.0:8000

在你的情况下,如果在Go项目的根路径中不存在'./asset'目录,或者你没有读取权限,http.Fileserver将返回404 - Not Found403 - Permission Denied

参考链接:

  1. http.Fileserver.ServeHTTP调用toHTTPError,该函数返回非特定的HTTP错误消息。
  2. 返回非特定的HTTP错误消息
英文:

Before trying to access your server using your own client, try accessing it with a CLI tool or browser.

Here's how you could do it using cURL:

curl -i -X GET http://0.0.0.0:8000

In your case, http.Fileserver will result in a 404 - Not Found or 403 - Permission Denied in case './asset' directory does not exist within your Go project's root path, or if you don't have read access.

Reference:

  1. http.Fileserver.ServeHTTP calls toHTTPError which returns non-specific HTTP error message.

答案6

得分: -3

根据您提供的代码,似乎您的Golang套接字服务器正在8000端口上运行,并且您正在尝试使用Kotlin从Android应用程序连接到它。

有几个可以检查以解决问题的事项:

  1. 确保服务器和Android模拟器在同一网络上:确保服务器和Android模拟器都连接到同一个网络,例如您的本地Wi-Fi网络。
  2. 更新服务器代码:在您的Golang服务器代码中,您正在使用/socket.io/命名空间进行socket.io事件,但在您的Android代码中,您正在尝试连接到/skt。确保命名空间匹配。如有必要,请更新Android代码以使用正确的命名空间。
  3. 使用服务器的IP地址而不是“localhost”:在Android代码中,尝试使用运行Golang服务器的计算机的IP地址,而不是使用“localhost”。如果服务器正在与Android模拟器运行在同一台机器上,则可以尝试使用IP地址10.0.2.2,它是一个特殊的别名,用于从Android模拟器引用主机机器的环回接口。

将Android代码中的这一行:

mSocket = IO.socket("http://localhost:8000/skt")

替换为:

mSocket = IO.socket("http://10.0.2.2:8000/socket.io/")

请注意,在此示例中,我假设服务器的命名空间为/socket.io/。

  1. 检查防火墙或安全设置:确保没有防火墙规则或安全设置阻止服务器和Android模拟器之间的通信。暂时禁用任何防火墙或安全软件可能有助于确定它们是否导致问题。

  2. 验证网络权限:仔细检查您的AndroidManifest.xml文件中是否声明了以下权限:

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

如果没有此权限,应用程序将无法连接到服务器。

通过解决这些问题,您应该能够解决Golang套接字服务器和Android应用程序之间的连接问题。

英文:

Based on the code you provided, it seems that your Golang socket server is running on port 8000 and you're trying to connect to it from an Android app using Kotlin.

There are a couple of things you can check to troubleshoot the issue:

  1. Ensure that the server and the Android emulator are on the same network: Make sure both the server and the Android emulator are connected to the same network, such as your local Wi-Fi network.
  2. Update the server code: In your Golang server code, you are using the /socket.io/ namespace for the socket.io events, but in your Android code, you are trying to connect to /skt. Make sure the namespaces match. Update the Android code to use the correct namespace if necessary.
    3.Use the server's IP address instead of "localhost": Instead of using "localhost" in the Android code, try using the IP address of the machine running the Golang server. If the server is running on the same machine as the Android emulator, you can try using the IP address 10.0.2.2, which is a special alias to refer to the host machine's loopback interface from the Android emulator.

Replace this line in your Android code:

mSocket = IO.socket(&quot;http://localhost:8000/skt&quot;)

with:

mSocket = IO.socket(&quot;http://10.0.2.2:8000/socket.io/&quot;)

Note that in this example, I've assumed the /socket.io/ namespace for the server.

  1. Check for any firewall or security settings: Ensure that there are no firewall rules or security settings blocking the communication between the server and the Android emulator. Temporarily disabling any firewall or security software could help identify if they are causing the issue.

  2. Verify the network permissions: Double-check that you have the

&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt;

permission declared in your AndroidManifest.xml file. Without this permission, the app won't be able to connect to the server.

By addressing these points, you should be able to troubleshoot and resolve the connectivity issue between your Golang socket server and the Android app.

huangapple
  • 本文由 发表于 2023年6月16日 15:26:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76487871.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定