使用Scala进行Socket.IO操作
背景 – 背景资料
如果你想要通过Socket.IO实现发布/订阅,我认为在Node.js上搭建服务器是一个可行的选择,但是有时候我们也希望在不同的系统之间进行协作。
用Scala编写Socket.IO
我尝试查找了一下是否存在支持 Socket.IO 的 Scala 库,但是我只发现了作为 Play Framework 模块存在的选项,没有找到通用的库。
这次服务器端使用了Akka HTTP进行编写,现在需要采用另一种方法进行实现。
使用Redis的发布/订阅功能
在Node.js端,只需要添加一些代码就可以进行以下适配。
const io = require('socket.io')(3000);
const redisAdapter = require('socket.io-redis');
io.adapter(redisAdapter({ host: 'localhost', port: 6379 }));
在Scala方面,需要自己编写(publish)来连接Redis。
我们将根据一篇关于Scala Redis客户端的文章进行选择。
参考来源于瀕死的たけぞう博客文章。
Sedis仅支持阻塞操作,所以排除掉。剩下的候选项是”scala-redis”或”rediscala”。
将要写入Redis的数据格式如下:
在这里,我们将把要发送的数据设置为data数组的第2个元素。
[
"emitter",
{
"type": 2,
"data": [
"イベント名",
{
"message": "Hello World!"
}
],
"nsp": "namespace"
},
{
"rooms": ["ルーム名"],
"flags": []
}
]
将使用MessagePack对其进行序列化的二进制数据写入redis。
在这里,由于先前的库“scala-redis”没有二进制写入方法,所以只能选择“rediscala”。
在Scala中,我们使用由MessagePack官方提供的”msgpack-scala”库。
这个库有点混乱,表示上述JSON的代码如下。
其他语言的库似乎可以通过一个方法将其转换为二进制,但在这个库中我没有找到…
val out = new ByteArrayOutputStream
val packer = MessagePack.newDefaultPacker(out)
packer.packArrayHeader(3)
// set emitter
packer.packString("emitter")
// set type 2
packer.packMapHeader(3)
packer.packString("type")
packer.packString("2")
// set data
packer.packString("data")
packer.packArrayHeader(2)
// set event name
packer.packString("イベント名")
// set data body
packer.packMapHeader(1)
packer.packString("message")
packer.packString("Hello World!")
// set namespace
packer.packString("nsp")
packer.packString("/")
packer.packMapHeader(2)
packer.packString(roomName)
packer.packArrayHeader(1)
packer.packString("ルーム名")
packer.packString("flags")
packer.packMapHeader(0)
packer.flush()
packer.close()
out.toByteArray
我們將使用rediscala將在此處獲取的二進制數據寫入Redis。
※RedisClient的構造函數已經以隱含方式接收ActorSystem,因此請根據各自的環境進行準備。
val redis = RedisClient(server,port)
redis.publish("チャンネル名", バイナリデータ)
数据接收
クライアント側では、設定したイベント名でデータを受信することができます。
socketio.on('イベント名', function(msg){
console.log('receive:' + JSON.stringify(msg));
});
总结
通过使用其他语言的相同机制,我们可以将数据写入Redis来实现与Scala介绍的相同功能。
※本次参考的网站
这个人用Python实现了类似的功能。
使用Python向socket.io-redis发射事件。