【问题标题】:Serialize object through network with Javascript - How to improve it?使用 Javascript 通过网络序列化对象 - 如何改进它?
【发布时间】:2014-11-14 12:42:19
【问题描述】:

我有一个 Message 类,可以在数据通过网络时进行序列化,我目前使用 JSON,主要是因为我对所有内容都使用 JSON。 (网络服务、套接字)。

我想改进序列化以使其尽可能好,我相信这里可以改进。

目的是使传输字符串更轻,尤其是在用于套接字(视频游戏)时,因为它将用于一切、每个响应客户端/服务器或服务器/客户端,甚至内部服务器或客户端方法,这是提供数据的常用方法。

Message 是一个复杂的对象,它还可以包含其他对象实例,例如 MessageLang,它将负责根据代码在客户端翻译句子。

到目前为止一切正常,结果如下:

Socket 服务器使用简单字符串发出

verbose: websocket writing 5:::{"name":"user.newAuthenticated","args":["Respond to emitter"]}

Socket 服务器发出简单的消息实例

verbose: websocket writing 5:::{"name":"user.newAuthenticated","args":["{\"m\":\"Respond to all clients\",\"d\":{},\"s\":1,\"t\":\"m\"}"]}

带有复杂消息实例的套接字服务器发出

verbose: websocket writing 5:::{"name":"user.newAuthenticated","args":["{\"m\":{\"m\":\"__12\",\"a\":{\"field\":\"name\",\"min\":3,\"max\":20}},\"d\":{\"key\":\"fakeKey\"},\"s\":1,\"t\":\"m\"}"]}

复杂的消息将呈现以下句子:

名称的最小长度为 3。最大长度为 20。 并且将在 data 中包含 key: "fakeKey"。只是为了解释它是如何工作的。

如你所见,消息越来越大,这是正常的,但我想知道我可以做些什么来更好地序列化:

  • 没有(空)时删除消息本身
  • 数据为空时也删除
  • 状态为假时删除(因为是默认值)
  • 我在套接字日志中看到 很多 \,因为它是 JSON,我相信这是一个问题,因为每次我添加一些东西时,我都会得到额外的字符不想。也许 JSON 不是一个好的选择,我应该以不同的方式序列化,首先在 JSON 中,如顶部的示例,然后在其他东西中,也许是二进制,如果它占用更少的空间。

你怎么看?

如果以某种方式加密另一种格式的消息是个好主意,那么加密的成本是否值得?因为加密它也需要一些时间,所以我只是想知道它是否不会仅仅移动问题,就像通过套接字发送消息所需的时间更少,因为它会更轻,但我们会使用更多的时间来加密它。只是想知道。

【问题讨论】:

  • 我在示例中没有看到 datastatus
  • 分别在ds有序列化。 m 表示message

标签: javascript json sockets serialization


【解决方案1】:

我的猜测是您的消息对象有两个字段(nameargs)。

减少消息长度的第一站是摆脱(相当无用的)外部对象并用数组替换它。所以一个空消息

{"name":"empty","args":[]}

会变成

["empty",[]]

甚至

["empty"]

接下来的事情是你在参数的序列化中有一个错误。您无需发送 JSON,而是将 JSON 数据包装在字符串中。示例:在经过身份验证的情况下,您发送

{"name":"user.newAuthenticated","args":["{\"m\":\"Respond to all clients\",\"d\":{},\"s\":1,\"t\":\"m\"}"]}

但你应该发送

{"name":"user.newAuthenticated","args":[{"m":"Respond to all clients","d":{},"s":1,"t":"m"}]}

相反。现在的问题是 args 是否是单个对象的列表。如果它始终是单个对象,那么您也可以摆脱[]。根据我上面建议的更改,这将为您提供:

["user.newAuthenticated",{"m":"Respond to all clients","d":{},"s":1,"t":"m"}]

这是相当不错的国际海事组织。如果您可以使(反)序列化程序正确处理默认值,则可以将其减少为:

["user.newAuthenticated",{"m":"Respond to all clients","s":1,"t":"m"}]

(即我们可以省略空的d 属性)。

【讨论】:

  • 实际上,消息本身分为四个字段:mdstmessagedatastatustypeMessage。您看到的name 是由套接字生成的,还有args,实际上包含消息本身。
  • 另外,backslashes 是由套接字本身添加的,而不是由我自己的对象添加的。这是因为 (我认为) 它必须只包含args 中的字符串,因为套接字只发送字符串。如果我在浏览器中进行测试,我会在控制台中得到以下信息:"{"m":{"m":"__12","a":{"field":"name","min":3,"max":20}},"d":{"key":"fakeKey"},"s":1,"t":"m"}"
  • WebSocket 本身不会向您发送的数据添加任何内容。您使用哪个框架通过 WebSockets 进行通信?
  • 向我们展示您用来获取问题中显示的 JSON 数据的代码。
  • 在这种情况下,sailsjs 似乎对消息进行了两次编码(它从中创建了一个 JSON 字符串,然后发送该字符串,而不是创建一个包含消息作为字段的 JS 对象)。我没有看到改善这一点的简单方法。也许sailsjs的人犯了一个错误,但也许他们有充分的理由对数据进行两次编码。
【解决方案2】:

对于 MMO,我认为必须向客户端发送最少的数据。如果一个socket被秒调用2xx/3xx,你必须尽可能减少通过socket发送的数据大小。

另一方面,它也消耗资源来加密服务器端的对象以发送对象的缩小版本......不是减少它并发送一个不减少的对象更好,所以我们不没有花费资源来加密它?

【讨论】:

    猜你喜欢
    • 2015-04-22
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 2014-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多