使用 ocaml Lwt 套接字
Working with ocaml Lwt sockets
我已经学习Ocaml 一个星期了,有些事情清楚了,有些则不太清楚。
我正在尝试编写一个简单的 Tic-Tac-Toe 服务器,通过 telnet 接受连接。就一句话。
我必须使用 Lwt 和 rigth,现在对我来说这似乎是一个黑暗的地方,因为我遇到了太多的语言特殊性。
代码开头:
let sock = Lwt_unix.socket Unix.PF_INET Unix.SOCK_STREAM 0
let setting_up_server_socket =
let sockaddr = (Unix.ADDR_INET(Unix.inet_addr_of_string "127.0.0.1", 23233)) in
Lwt_unix.set_close_on_exec sock;
Lwt_unix.setsockopt sock Unix.SO_REUSEADDR true;
Lwt_unix.bind sock sockaddr;
Lwt_unix.listen sock 20
好的,明白了。服务器套接字设置为侦听客户端连接。让我们尝试获得第一位客人:
let handle_income =
Lwt_unix.accept sock;;
似乎很清楚,但是:
val handle_income : (Lwt_unix.file_descr * Lwt_unix.sockaddr) Lwt.t = <abstr>
我在这里堆积。我什至不知道如何向客户端套接字发送消息。
不像一般的Unix.accept它returns('a * 'b)Lwt.t。一些问题:
- 我怎样才能从中获得纯客户端 "Lwt_unix.file_descr"?
- ('a * 'b) Lwt.t。是一个属于 Lwt.t 对象的元组,不是吗?还是只是一个领域?我一头雾水
P.S。对不起,如果我的英语不可接受。我很久以前就在学习它。由于问题已经被问到,请提供一条建议,我可以从哪里获得有关 Ocaml 的最佳信息。最好一个均值short/clearness。由于阅读 O'REILLY,我立即忘记了 5 分钟前我正在阅读的内容,因为永远不清楚作者所说的这个或那个是用来做什么的。 Ocaml 与 Java 和我开始使用的 JS 完全不同。
'a Lwt.t
类型的值表示一个线程,一旦准备就绪(或者出现错误,就会计算出 'a
类型的值)。从 'a Lwt.t
获取 'a
的唯一方法是将其绑定到另一个函数,该函数将在 'a Lwt.t
线程完成且数据准备就绪时尽快调用。您可以使用 Lwt.bind
函数进行绑定,也可以在中缀符号 >>=
.
中使用
例如:
let process_client fd =
Lwt_unix.accept fd >>= fun (cli,sock) ->
let chan = Lwt_io.(of_fd ~mode:output cli) in
Lwt_io.fprintf chan "hi there, and bye!" >>= fun () ->
Lwt_io.close chan
这使用中缀表示法,您可以将其重写得更冗长:
let reply chan =
Lwt_io.fprintf chan "hi there, and bye!"
let finish chan = Lwt_io.close chan
let create_chan = Lwt_io.(of_fd ~mode:output cli)
let process_client fd =
let accept_t = Lwt_unix.accept fd in
let chan_t = Lwt.map accept_t create_chan in
let reply_t = Lwt.bind accept_t reply in
Lwt.bind reply_t finish
其中 _t
表示 thread
。即,accept_t
是一个最终将 return 一对文件描述符和套接字地址的线程。 chan_t
是一个将 return 通道(用于执行缓冲 io)的线程。
Lwt
还支持特殊语法。实际上支持两种语法,旧语法使用 camlp4,新语法使用 ppx。在旧语法中,可以将 process_client
函数写成如下形式:
let process_client fd =
lwt (cli,sock) = Lwt_unix.accept fd in
let chan = Lwt_io.(of_fd ~mode:output cli) in
lwt () = Lwt_io.fprintf chan "hi there, and bye!" in
Lwt_io.close chan
lwt
是 let
的一种特殊形式,它不仅将名称绑定到值,而且还等待它们求值。
希望我回答了你所有的问题。您可能还会发现这个 library 很有趣。
P.S。我没有测试代码,所以如果您有任何问题,请不要犹豫。
P.P.S。我留下了一个适当的 shutdown
过程,以保持代码简单。
我已经学习Ocaml 一个星期了,有些事情清楚了,有些则不太清楚。 我正在尝试编写一个简单的 Tic-Tac-Toe 服务器,通过 telnet 接受连接。就一句话。 我必须使用 Lwt 和 rigth,现在对我来说这似乎是一个黑暗的地方,因为我遇到了太多的语言特殊性。 代码开头:
let sock = Lwt_unix.socket Unix.PF_INET Unix.SOCK_STREAM 0
let setting_up_server_socket =
let sockaddr = (Unix.ADDR_INET(Unix.inet_addr_of_string "127.0.0.1", 23233)) in
Lwt_unix.set_close_on_exec sock;
Lwt_unix.setsockopt sock Unix.SO_REUSEADDR true;
Lwt_unix.bind sock sockaddr;
Lwt_unix.listen sock 20
好的,明白了。服务器套接字设置为侦听客户端连接。让我们尝试获得第一位客人:
let handle_income =
Lwt_unix.accept sock;;
似乎很清楚,但是:
val handle_income : (Lwt_unix.file_descr * Lwt_unix.sockaddr) Lwt.t = <abstr>
我在这里堆积。我什至不知道如何向客户端套接字发送消息。 不像一般的Unix.accept它returns('a * 'b)Lwt.t。一些问题:
- 我怎样才能从中获得纯客户端 "Lwt_unix.file_descr"?
- ('a * 'b) Lwt.t。是一个属于 Lwt.t 对象的元组,不是吗?还是只是一个领域?我一头雾水
P.S。对不起,如果我的英语不可接受。我很久以前就在学习它。由于问题已经被问到,请提供一条建议,我可以从哪里获得有关 Ocaml 的最佳信息。最好一个均值short/clearness。由于阅读 O'REILLY,我立即忘记了 5 分钟前我正在阅读的内容,因为永远不清楚作者所说的这个或那个是用来做什么的。 Ocaml 与 Java 和我开始使用的 JS 完全不同。
'a Lwt.t
类型的值表示一个线程,一旦准备就绪(或者出现错误,就会计算出 'a
类型的值)。从 'a Lwt.t
获取 'a
的唯一方法是将其绑定到另一个函数,该函数将在 'a Lwt.t
线程完成且数据准备就绪时尽快调用。您可以使用 Lwt.bind
函数进行绑定,也可以在中缀符号 >>=
.
例如:
let process_client fd =
Lwt_unix.accept fd >>= fun (cli,sock) ->
let chan = Lwt_io.(of_fd ~mode:output cli) in
Lwt_io.fprintf chan "hi there, and bye!" >>= fun () ->
Lwt_io.close chan
这使用中缀表示法,您可以将其重写得更冗长:
let reply chan =
Lwt_io.fprintf chan "hi there, and bye!"
let finish chan = Lwt_io.close chan
let create_chan = Lwt_io.(of_fd ~mode:output cli)
let process_client fd =
let accept_t = Lwt_unix.accept fd in
let chan_t = Lwt.map accept_t create_chan in
let reply_t = Lwt.bind accept_t reply in
Lwt.bind reply_t finish
其中 _t
表示 thread
。即,accept_t
是一个最终将 return 一对文件描述符和套接字地址的线程。 chan_t
是一个将 return 通道(用于执行缓冲 io)的线程。
Lwt
还支持特殊语法。实际上支持两种语法,旧语法使用 camlp4,新语法使用 ppx。在旧语法中,可以将 process_client
函数写成如下形式:
let process_client fd =
lwt (cli,sock) = Lwt_unix.accept fd in
let chan = Lwt_io.(of_fd ~mode:output cli) in
lwt () = Lwt_io.fprintf chan "hi there, and bye!" in
Lwt_io.close chan
lwt
是 let
的一种特殊形式,它不仅将名称绑定到值,而且还等待它们求值。
希望我回答了你所有的问题。您可能还会发现这个 library 很有趣。
P.S。我没有测试代码,所以如果您有任何问题,请不要犹豫。
P.P.S。我留下了一个适当的 shutdown
过程,以保持代码简单。