https://kotlinlang.org logo
Title
h

Hamza Maqsood

01/17/2022, 2:29 PM
hello channel, a quick question about websockets in ktor for example in node js(socket.io), we can do something like this: socket.broadcast.to(socket).emit('event_name', JSON.stringify(data)) the event_name can be used to differentiate between event types on client side, how to do something like this in ktor? all I can see in ktor examples is that you send message as: socket.send(Frame(data)) Is there a neat way to send the event type along with the data?
a

Aleksei Tirman [JB]

01/18/2022, 7:50 AM
You can encode an event in a frame itself and write methods that hide this detail. Also, there is a feature request to support socket.io interface out of the box.
h

Hamza Maqsood

01/18/2022, 8:40 AM
just for clarification, so you mean that I can have a base class(that'll hold the event value and the generic data value) and based on the event value, I parse the data value, right? or is there a better way?
a

Aleksei Tirman [JB]

01/18/2022, 10:05 AM
I mean to have an extension function for a
SendChannel<Frame>
object that internally encodes event in a
Frame
. Here is an example:
suspend fun SendChannel<Frame>.emit(event: String, frame: Frame) {
    val packet = BytePacketBuilder().apply {
        append(event)
        writeFully(frame.data)
    }.build()

    send(Frame.Binary(true, packet.readBytes()))
}
And the calling side will look like this:
client.webSocket("<ws://0.0.0.0:4444/socket>") {
    outgoing.emit("event", Frame.Text("hello"))
}
h

Hamza Maqsood

01/18/2022, 11:01 AM
thanks alot man, I'll give it a try
It works on the server side, I have tried connecting to the websocket from android using the socketio java client library but it's not connecting, working through postman but not from the app, I have enabled the internet permissions in manifest file and also allowed clear text traffic, still not connecting from android so I am assuming that ktor websockets aren't compatible with socketio clients, is that so? also if I use ktor client on android to connect to the websockets, how can I extract the event using ktor websocket client?
a

Aleksei Tirman [JB]

01/19/2022, 8:12 AM
They should be compatible but I'm not sure. I suggest using a network protocol analyzer like WireShark to determine if the Websockets frames are actually sent or not. To extract an event from the frame you need to understand how Socket.IO encodes it by analyzing frames.
h

Hamza Maqsood

01/19/2022, 8:20 AM
I am trying ktor client now on Android, but I am not sure how can I extract the event when I receive the frames on Android side from this:
val packet = BytePacketBuilder().apply {
        append(event)
        writeFully(frame.data)
    }.build()
on android, I can do something like
socket?.incoming
    ?.receiveAsFlow()
    ?.filter { it is Frame.Binary }
now how to separate data and event from this stream? because the length will be different for the event string
a

Aleksei Tirman [JB]

01/19/2022, 8:25 AM
This was just an example 🙂 You need to encode events in a way to deterministically read them on the other side.
h

Hamza Maqsood

01/19/2022, 8:31 AM
Oh I see, pardon for my ignorance, I am a sort of a newbie here, undergrad student still what if I make each event string of length of 32, and for shorter strings, I append some character like # to fulfill the length, and on android side, when I get the event string of length 32, I can do something like event.replace("#", "") or is there a neater way?
a

Aleksei Tirman [JB]

01/19/2022, 8:59 AM
I would encode the length of an event string in the first byte (like in Pascal strings) so you could have events with up to 255 characters.
h

Hamza Maqsood

01/19/2022, 9:00 AM
I see, that's neat I'll give it shot, thanks