作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想用 OCaml 中的服务器做一个客户端 js_of_ocaml 应用程序,约束如下所述,我想知道下面的方法是否正确,或者是否有更有效的方法。服务器有时会发送大量数据(> 30MB)。
为了使客户端和服务器之间的通信更安全、更高效,我在 .mli 文件中共享一个类型 t,如下所示:
type client_to_server =
| Say_Hello
| Do_something_with of int
type server_to_client =
| Ack
| Print of string * int
loading
状态期间收到的编码对象(如果可能) ,而不仅仅是在
done
状态期间)。
responseText
内容类型为
application/octet-stream
的 XMLHTTPRequest .
responseText
的响应时, 因为 JavaScript 的字符串是 UTF-16,所以进行了编码转换。但是编码的对象是二进制数据,为了检索我们的二进制数据,我们做了必要的事情(通过用
x-user-defined
覆盖字符集并在
responseText
字符串的每个字符上应用掩码)。
let process_request req =
let res = process_response req in
let s = Marshal.to_string res [] in
send s
caml_marshal_data_size
需要一个 MlString。但是在流模式下,我们不想将javascript的字符串转换成MlString(它可以迭代完整的字符串),我们更喜欢做大小验证和解码(以及编码问题的掩码的应用)在读取的字节上。因此,我用 javascript 编写了自己的元组元组。
external marshal_total_size : Js.js_string Js.t -> int -> int = "my_marshal_total_size"
external marshal_from_string : Js.js_string Js.t -> int -> 'a = "my_marshal_from_string"
let apply (f:server_to_client -> unit) (str:Js.js_string Js.t) (ofs:int) : int =
let len = str##length in
let rec aux pos =
let tsize =
try Some (pos + My_primitives.marshal_total_size str pos)
with Failure _ -> None
in
match tsize with
| Some tsize when tsize <= len ->
let data = My_primitives.marshal_from_string str pos in
f data;
aux tsize
| _ -> pos
in
aux ofs
let reqcallback f req ofs =
match req##readyState, req##status with
| XmlHttpRequest.DONE, 200 ->
ofs := apply f req##responseText !ofs
| XmlHttpRequest.LOADING, 200 ->
ignore (apply f req##responseText !ofs)
| _, 200 -> ()
| _, i -> process_error i
let send (f:server_to_client -> unit) (order:client_to_server) =
let order = Marshal.to_string order [] in
let msg = Js.string (my_encode order) in (* Do some stuff *)
let req = XmlHttpRequest.create () in
req##_open(Js.string "POST", Js.string "/kernel", Js._true);
req##setRequestHeader(Js.string "Content-Type",
Js.string "application/octet-stream");
req##onreadystatechange <- Js.wrap_callback (reqcallback f req (ref 0));
req##overrideMimeType(Js.string "application/octet-stream; charset=x-user-defined");
req##send(Js.some msg)
//Provides: my_marshal_header_size
var my_marshal_header_size = 20;
//Provides: my_int_of_char
function my_int_of_char(s, i) {
return (s.charCodeAt(i) & 0xFF); // utf-16 char to 8 binary bit
}
//Provides: my_marshal_input_value_from_string
//Requires: my_int_of_char, caml_int64_float_of_bits, MlStringFromArray
//Requires: caml_int64_of_bytes, caml_marshal_constants, caml_failwith
var my_marshal_input_value_from_string = function () {
/* Quite the same thing but with a custom Reader which
will call my_int_of_char for each byte read */
}
//Provides: my_marshal_data_size
//Requires: caml_failwith, my_int_of_char
function my_marshal_data_size(s, ofs) {
function get32(s,i) {
return (my_int_of_char(s, i) << 24) | (my_int_of_char(s, i + 1) << 16) |
(my_int_of_char(s, i + 2) << 8) | (my_int_of_char(s, i + 3));
}
if (get32(s, ofs) != (0x8495A6BE|0))
caml_failwith("MyMarshal.data_size");
return (get32(s, ofs + 4));
}
//Provides: my_marshal_total_size
//Requires: my_marshal_data_size, my_marshal_header_size, caml_failwith
function my_marshal_total_size(s, ofs) {
if ( ofs < 0 || ofs > s.length - my_marshal_header_size )
caml_failwith("Invalid argument");
else return my_marshal_header_size + my_marshal_data_size(s, ofs);
}
最佳答案
您是否尝试使用 EventSource https://developer.mozilla.org/en-US/docs/Web/API/EventSource
您可以流式传输 json 数据而不是编码(marshal)数据。Json.unsafe_input
应该比解码快。
class type eventSource =
object
method onmessage :
(eventSource Js.t, event Js.t -> unit) Js.meth_callback
Js.writeonly_prop
end
and event =
object
method data : Js.js_string Js.t Js.readonly_prop
method event : Js.js_string Js.t Js.readonly_prop
end
let eventSource : (Js.js_string Js.t -> eventSource Js.t) Js.constr =
Js.Unsafe.global##_EventSource
let send (f:server_to_client -> unit) (order:client_to_server) url_of_order =
let url = url_of_order order in
let es = jsnew eventSource(Js.string url) in
es##onmessage <- Js.wrap_callback (fun e ->
let d = Json.unsafe_input (e##data) in
f d);
()
type server_to_client =
| Ack
| Print of string * int
deriving (Json)
let process_request req =
let res = process_response req in
let data = Json_server_to_client.to_string res in
send data
Deriving_json
使用 js_of_ocaml 中值的内部表示将 ocaml 值序列化为 json。
Json.unsafe_input
是
Deriving_json
的快速解串器依赖于浏览器原生 JSON 支持。
Deriving_json
和
Json.unsafe_input
处理 ocaml 字符串编码
关于ocaml - 使用 OCaml 编码数据通信客户端 - 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25055631/
我们已经通过C# winforms项目完成了SQL Server与远程MySQL(WEB)数据库(Unix平台)之间的数据通信。所有数据都通过定制软件进行更新。 我们想要的是,当我们更新、插入行或执行
我是一名优秀的程序员,十分优秀!