【发布时间】:2021-05-24 22:56:29
【问题描述】:
我正在尝试使用 Native Socket.IO 将 Android 应用程序连接到 Express 服务器。服务器有一个非常简单的工作(目前),接收 4200 上的传入流量并将其发送回其他客户端,以便他们可以显示它 - 尽管现在我只是调试服务器和这个 Android 实现,希望得到漂亮的文本“客户端已连接”
这是服务器 API
// Socket handling
io.on( 'connection', (socket) => {
console.log('Client Connected');
socket.on('temperature', (data) => {
console.log('Engine Data:' + data);
// For now, just spit data back to all other connected clients
socket.broadcast.emit('temperature', {num: data});
});
socket.on('disconnect', ()=> {
console.log('Client disconnected');
});
});
目前这适用于发送随机数的基本 Node.JS 客户端,所以我知道服务器可以正常工作:
<script>
var socket = io('http://localhost:4200');
socket.on('connection', (socket) => {
console.log('Connection Success');
});
let temperature = 0;
//Send stuff every 100ms
setInterval(() => {
let lastTemp = temperature < 90 ? temperature : 0;
temperature = Math.floor(Math.random() * 5) + lastTemp;
socket.emit('temperature', temperature);
}, 50);
</script>
但是我的 Android 应用程序有问题 - 服务器没有像浏览器客户端那样记录连接,虽然它没有在连接上引发异常,但套接字 ID 只是 NULL 并且状态是“不调试时已连接”。我一直在关注不同的tutorials 并尝试在 StackOverflow 上发布解决方案,因此我目前的主要活动是利用搜索栏获取如下所示的虚拟值:
//! SocketIO stuff
import com.github.nkzawa.socketio.client.IO
import com.github.nkzawa.socketio.client.Socket
class MainActivity : AppCompatActivity() {
//! Instantiate socket for other functions that will utilize it - this will likely be part of its own class
lateinit var mSocket: Socket
//! Main Activity creation
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.toolbar))
//! SeekBar for setting dummy input by user
val seek: SeekBar = findViewById<SeekBar>(R.id.seekBar)
seek.max = 100
seek.progress = 50
//! CurrentVal is our current dummy sensor value
var currentVal: Int;
//! Connect to web server
try {
//! Configure library options
val options = IO.Options()
options.reconnection = true
options.forceNew = true
//This address is the way you can connect to localhost with AVD(Android Virtual Device)
mSocket = IO.socket("http://10.0.2.2:4200/", options) // emulator loopback address
} catch (e: Exception) {
e.printStackTrace()
Log.d("Failure", "Failed to connect to server")
}
Log.d("Connected", "socket ID:${mSocket.id()}")
mSocket.connect()
seek.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
...
override fun onStopTrackingTouch(seek: SeekBar) {
//Progress stopped
//get value from seek bar
currentVal = seek.progress
//Send the value via our socket
mSocket.emit("temperature", currentVal)
}
})
}
根据其他 StackOverflow 建议的反馈,我的清单包括以下内容
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
...
android:usesCleartextTraffic="true"
...
但是,服务器并未反映客户端已连接。当我查看 Wireshark 时,我看到确实有一个端口 55735 正在尝试连接到在 4200 上运行的服务器,但是服务器响应“400 Bad Request”并且 JSON 字符串值为“不支持的协议版本”
2899 23.395504 127.0.0.1 127.0.0.1 HTTP/JSON 287 HTTP/1.1 400 Bad Request , JavaScript Object Notation (application/json)
这让我相信我正在使用的 Socket.IO 库和服务器上的 Socket.IO 存在一些兼容性问题。我正在使用的教程在 Socket.IO 网站上......但它也是从 2015 年开始的。我应该按照不同的方式在 Android 上使用 Socket.IO 吗?
【问题讨论】:
-
您的服务器在哪里运行?您的 Android 应用在哪里运行?
-
我看到了 127.0.0.1 和 10.0.2.2,您可以向我们解释一下。
-
// emulator loopback address127.0.0.1号也是模拟器环回地址。 -
//This address is the way you can connect to localhost with AVD(Android Virtual Device)。不。使用 10.0.2.2,模拟器上的客户端可以连接到运行模拟器的电脑上运行的服务器。 -
服务器在 PC 上,Android 在同一台 PC 上的模拟器上运行。听起来我的地址是正确的......
标签: android node.js express sockets socket.io