- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我遇到了一个问题。我在 Erlang/OTP 上有一个 iOS 客户端和一个 tcp 服务器。客户端假设通过 GCDAsynchSocket 向服务器发送和接收消息。如果我需要发送消息但它不能作为接受者,它工作得很好,因为客户端必须调用这个委托(delegate)方法:
/**
* 当套接字完成将请求的数据读入内存时调用。
* 如果有错误则不调用。
**/
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;
问题是服务器关闭了调用另一个委托(delegate)方法的连接(- (void)socketDidDisconnect:(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/
我遇到了一个问题。我在 Erlang/OTP 上有一个 iOS 客户端和一个 tcp 服务器。客户端假设通过 GCDAsynchSocket 向服务器发送和接收消息。如果我需要发送消息但它不能作为接受
我是一名优秀的程序员,十分优秀!