Benedicht / BestHTTP-Issues

Issue tracking repo for the Best HTTP and all related Unity plugins.
https://assetstore.unity.com/publishers/4137
12 stars 1 forks source link

socketio: an `On` subscription without deserializer/strongly-typed? #160

Closed somedeveloper00 closed 1 year ago

somedeveloper00 commented 1 year ago

Hi. I was wondering, is this achievable with the current version? something like so:

socket.On("myEvent", strData => {
  // use my custom serialization methods on `strData` here
});

in a way that it would catch all the received data in that event, without going through the process of deserialization.

Thanks in advance!

Benedicht commented 1 year ago

No, it isn't possible. But i would be interested in knowing what would be your use-case.

somedeveloper00 commented 1 year ago

No, it isn't possible. But i would be interested in knowing what would be your use-case.

Thanks for the response. My use case is that I want to deserialize the received data myself, using my Json serializer, because I've made so many custom rules for the classes (i.e. shorter names or list population rules). Correct me if I'm wrong, but doesn't socket.io sends object data[1] in from of string anyway? so I gathered it would make sense to use that raw input and process it myself.

[1]: this is what I mean by object data:

socket.emit('pong', {
  'id': 123,
  'time': new Date().time();
});

(excuse my horrible syntax errors :p I'm no javascript user)

Benedicht commented 1 year ago

You would want to parse only a few events or all of them? Because you can already wrote a custom parser, like the JSON.NET one, and use it instead of the default one.

If only a few, who should handle the event calling? Or event calling would be custom too, like an override of the default parsing&event handling?

Correct me if I'm wrong, but doesn't socket.io sends object data[1] in from of string anyway? It depends, with MessagePack, it will send only binary data. Also, when the sent data contains binary, the sender has to create more than one packet, and the receiver must must wait for all the packets to reconstruct the original object (you could send a buffer with binary data in your pong object in your example).

somedeveloper00 commented 1 year ago

with MessagePack, it will send only binary data. Also, when the sent data contains binary, the sender has to create more than one packet, and the receiver must must wait for all the packets to reconstruct the original object (you could send a buffer with binary data in your pong object in your example).

I see, I didn't know that. In that case, it'll be faster to get the correct object structure in BestHTTP's socket.On<PongObject>("pong", (data) => {...});, rather than serializing it to string and back to object, if I understand correctly.

You would want to parse only a few events or all of them? Because you can already wrote a custom parser, like the JSON.NET one, and use it instead of the default one.

For my current use-case, I need this for a specific event, let's say "complexEvent", and the only reason for doing so is performance. I would like to do only one deserialization, and the current parsers in BestHTTP aren't able to do that. So one solution, as you suggested, would be to write a new one for my use. But because that'll be too complex, I came here to see if it's possible to get just the raw string, which would make my job easier.

For now however I've modified the server to send datas only in string[1] and receive them as string in BestHTTP[2]. This is most performant on client side, don't know about server though; to be frank I don't know much about underlaying data-sending of socketio but anyways, the performance I tested seems good enough (much better than when I sent object and received it as Dictionary<string,object> with BestHTTP's deserializer)

[1]:

socket.emit('complexEvent', JSON.stringify({...}));

[2]:

socket.On<string>("complexEvent", (strData) => {...});
Benedicht commented 1 year ago

For now however I've modified the server to send datas only in string[1] and receive them as string in BestHTTP[2]. This is most performant on client side, don't know about server though; to be frank I don't know much about underlaying data-sending of socketio but anyways, the performance I tested seems good enough (much better than when I sent object and received it as Dictionary<string,object> with BestHTTP's deserializer)

I think that's basically what the default json serializer do on the server side.

the performance I tested seems good enough (much better than when I sent object and received it as Dictionary<string,object> with BestHTTP's deserializer)

How's complex and large your data is? Do you use the default json parser?

Also, i can recommend to try out the MessagePack parser too.

somedeveloper00 commented 1 year ago

Thanks for the responce. 🙏🙏

I think that's basically what the default json serializer do on the server side.

yeah more burden on server... it's not good, I know. Just testing things.

How's complex and large your data is? Do you use the default json parser?

Just checked a sample and it's 5kb in size. yes, I was using default json parser in SocketManager, on a simpler type (with lots of serialized strings in it), to then convert it to a more complex object using our customized serializer. like so:

manager.socket.On<SimplifiedData>("complexEvent", simplified => {
   // `simplified` has lots of strings that should be deserialized
  ComplexData complexData = new ComplexData(simplified); // our serializer does it's work in here
  ...
});

The reason being that the default serializer couldn't correctly deserialize it.

What I mean by customized serializer is basically just NewtonSoft with custom logics before/after (de)serialization. Imagine, if i want to create an Action supertype that has PauseAction and ResumeAction children. I would do something similar to this for (de)serialization:

class Action {
  public static Action Deserialize(string data) {
    var jobj = JsonConvert.Deserailize<JObject>(data); // JObject is super-fast, it uses lazy deserialization as far as i know
    if (jobj["type"] == "pause") return jobj.ToObject<PauseAction>("data");
    if (jobj["type"] == "resume") return jobj.ToObject<ResumeAction>("data");
  }
}
class PauseAction : Action { string pauseReason; }
class ResumeAction : Action { string resumeReason; }

and json would look similar to

// a pause action
{ 
  "type": "pause",
  "data": { "pauseReason": "..." }
}
// a resume action
{ 
  "type": "resume"
  "data": { "resumeReason": "..." }
}

I hope im making sense, I think I'm overcomplicating it🤦in short, if the received data is always json, I would like to be able to receive it as json, like in Socketio2 version of BestHTTP. But since that's apparently impossible, I'll take a look at MassgePackParser; If you have a better idea for this use-case, I'd appreciate it if you help out!

But as for this issue, I think this can be closed now.