tcp - 使用 Ninenine 牧场实现 Long live tcp 连接
问题描述
我正在尝试与ninnenine ranch erlang library实现长期 TCP 连接。但是查看文档我看不到这样做的方法。我也编写了自己的牧场协议,如下所示
start_link(Ref, _Socket, Transport, Opts) ->
Pid = spawn_link(?MODULE, init, [Ref, Transport, Opts]),
{ok, Pid}.
init(Ref, Transport, _Opts = []) ->
{ok, Socket} = ranch:handshake(Ref),
loop(Socket, Transport).
loop(Socket, Transport) ->
case Transport:recv(Socket, 0, 5000) of
{ok, Data} when Data =/= <<4>> ->
%% Transport:send(Socket, Data),
io:format("~w Connction accpted~n", [Data]);
_ -> ok
%%, Transport:close(Socket)
end.
正如你所看到的,我已经评论了Transport:close(Socket)
并且我没有向客户发送任何回复,因为Transsport:send(socket,Data)
也评论认为这将解决问题,但仍然,我的连接在打开时立即关闭。我有一个如下所示的 golang 客户端
package main
import (
"fmt"
"log"
"net"
)
func main(){
conn, err := net.Dial("tcp", "localhost:5555")
if err != nil {
fmt.Println(err)
}
fmt.Println(conn /*, i*/)
conn.Write(XMLData)
buffer := make([]byte, 10024)
n, err := conn.Read(buffer)
fmt.Println(buffer[:n])
//conn.Close()
}
我虽然是在牧场超时造成的。我搜索了,我发现在牧场中,在文件 src/ranch_tcp.erl 中,我们有如下实现的函数监听
listen(Opts) ->
Opts2 = ranch:set_option_default(Opts, backlog, 1024),
Opts3 = ranch:set_option_default(Opts2, nodelay, true),
Opts4 = ranch:set_option_default(Opts3, send_timeout, 30000),
Opts5 = ranch:set_option_default(Opts4, send_timeout_close, true),
%% We set the port to 0 because it is given in the Opts directly.
%% The port in the options takes precedence over the one in the
%% first argument.
gen_tcp:listen(0, ranch:filter_options(Opts5, disallowed_listen_options(),
[binary, {active, false}, {packet, raw}, {reuseaddr, true}])).
如您所见,有一个特别是 Opts5Opts5 = ranch:set_option_default(Opts4, send_timeout_close, true)
和 Opts4的超时选项Opts4 = ranch:set_option_default(Opts3, send_timeout, 30000),
。我禁用了它们,但仍然无法正常工作。那么我应该怎么做才能使用牧场建立长期有效的 tcp 连接。
解决方案
你的协议实现有缺陷
loop(Socket, Transport) ->
case Transport:recv(Socket, 0, 5000) of
{ok, Data} when Data =/= <<4>> ->
%% Transport:send(Socket, Data),
io:format("~w Connction accpted~n", [Data]);
_ -> ok
%%, Transport:close(Socket)
end.
您不会loop/2
在任何 case 子句分支中递归调用,因此当loop/2
返回使 tcp 连接断开时,您的协议进程会终止。
推荐阅读
- css - SAPUI5 如何正确更改选择项目背景颜色?
- python - UnicodeEncodeError:“ascii”编解码器无法在位置 0 编码字符“\u012b”:序数不在范围内(128)
- javascript - 如何将 cytoscape 图形导出为可以使用 microsoft office 编辑的格式
- laravel - 一对一关系建议
- java - 程序将 *.csv 文件读入数组并打印内容。要求打印索引号
- django - “用户”对象没有属性“配置文件”
- node.js - 谷歌搜索控制台 API,google.webmasters.searchanalytics.query“startDate 字段是必需的”
- javascript - 如何通过按 Enter 按钮将焦点设置在 a 中的下一个“启用”输入框上
- android - 有没有可能改变机器人不确定进度条的速度(让它变慢)?
- html - 将厘米转换为像素,转换公式?