gpt4 book ai didi

ios - Erlang gen_tcp 关闭被 GCDAsynchSocket 弄错的端口

转载 作者:可可西里 更新时间:2023-11-01 02:46:42 24 4
gpt4 key购买 nike

我遇到了一个问题。我在 Erlang/OTP 上有一个 iOS 客户端和一个 tcp 服务器。客户端假设通过 GCDAsynchSocket 向服务器发送和接收消息。如果我需要发送消息但它不能作为接受者,它工作得很好,因为客户端必须调用这个委托(delegate)方法:

/**
* 当套接字完成将请求的数据读入内存时调用。
* 如果有错误则不调用。
**/
- (void)soc​​ket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;

问题是服务器关闭了调用另一个委托(delegate)方法的连接(- (void)soc​​ketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err;).如何在客户端完成从服务器读取数据,以及如何在服务器上保留工作连接,直到客户端自行断开连接? iOS 客户端从服务器获取字节但无法正常关闭连接。

Erlang 服务器的一部分:

-behaviour (gen_server).

-export ([start_link/0, check_data/1]).

%%gen_server callbacks
-export ([init/1, handle_call/3,
handle_cast/2, handle_info/2,
terminate/2, code_change/3]).

-define (PORT, 1477).

start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [?PORT], []).


init([Port]) ->
process_flag(trap_exit, true),
{ok, Listen} = gen_tcp:listen(Port,
[{active, false},
binary,
{reuseaddr, true}]),
spawn(fun() ->
accept_parallel(Listen) end),
io:format("~p started~n", [?MODULE]),
{ok, 0}.

accept_parallel(Listen) ->
{ok, Socket} = gen_tcp:accept(Listen),
spawn(fun() -> accept_parallel(Listen) end),
loop(Socket).

handle_call(Request, _From, N) ->
{reply, Request, N + 1}.

handle_cast(_Msg, N) ->
{noreply, N}.

handle_info(_Info, N) ->
{noreply, N}.

terminate(_Reason, _N) ->
io:format("~p stoped~n", [?MODULE]),
ok.

code_change(_OldVsn, N, _Extra) -> {ok, N}.

loop(Socket) ->
case gen_tcp:recv(Socket, 0) of
{ok, Bin} ->
case check_data(Bin) of
ok ->
gen_tcp:send(Socket, "ok");
{error, _Data} ->
gen_tcp:send(Socket, "error")
end;
{error, Reason} ->
exit(Reason)
end.

我可以在向客户端发送消息后设置超时,但无论如何我怎样才能完成接受数据呢?

更新:我只需要连接一次即可通过向客户端发送 token 来证明授权。

最佳答案

你的循环没有循环,所以一旦你的 case 表达式被评估,你的进程就会退出(没有什么可做的)并且 gen_tcp 会在进程退出时为你关闭连接。您需要在 loop/1 的末尾添加 loop(Socket):

loop(Socket) ->
case gen_tcp:recv(Socket, 0) of
% stuff...
end,
loop(Socket).

不过,就个人而言,我更喜欢使用 gen_tcp 遵循更通用的 receive 风格,而不是 gen_tcp:recv/2 ,如本例所示:

loop(S) ->
inet:setopts(S,[{active,once}]),
receive
{tcp,S,Data} ->
Answer = process(Data), % business logic here
gen_tcp:send(S,Answer),
loop(S);
{tcp_closed,S} ->
io:format("Socket ~w closed [~w]~n",[S,self()]),
ok
end.

以上示例摘自 gen_tcp文档,并且与您将看到人们实现混合套接字样式的方式非常相似。至少对我来说,这种方法在防止数据泛滥的同时理清了我的推理。

关于ios - Erlang gen_tcp 关闭被 GCDAsynchSocket 弄错的端口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26201788/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com