gpt4 book ai didi

tcp - 如何在 erlang gen_tcp 中同时处理一个客户端?

转载 作者:可可西里 更新时间:2023-11-01 02:45:57 26 4
gpt4 key购买 nike

我有一个监听 Ip:Port 的 TCP 服务器。

listen(Ip, Port) ->
Opts = [
binary,
{active, false},
{packet, 0},
{reuseaddr, true},
{ip, Ip}
],

case gen_tcp:listen(Port, Opts) of
{ok, ListenSock} ->
?MODULE:loop_accept(ListenSock);
{error, Reason} ->
exit(Reason)
end.

loop_accept(ListenSock) ->
{ok, Sock} = gen_tcp:accept(ListenSock),
?MODULE:loop(Sock),
?MODULE:loop_accept(ListenSock).

loop(Sock) ->
case gen_tcp:recv(Sock, 0) of
{ok, Data} ->
gen_tcp:send(Sock, [<<"Response: ">>, Data]),
?MODULE:loop(Sock);

{error, Reason} ->
ok
end.

任务:当一个客户端连接到 Ip:Port(例如 telnet Ip Port)时,必须断开另一个尝试连接的客户端。换句话说,独占使用 Ip:Port。

问题:

  • 如何使用 gen_tcp 模块在 Erlang 上实现它?
  • 是否可以通过 gen_tcp:listen 选项解决?
  • 如何以编程方式断开 Erlang 中的尝试连接?

附言我是 erlang 的新手。

最佳答案

首先,当您指定 {packet, 0} 时,您不能像那样recv()。阅读此 answer about gen_tcp .

服务器可以:

  1. Pid = spawn(?MODULE, loop, [Sock])

  2. 监控 #1 中的进程:

    Ref = monitor(process, Pid)

    但是为了防止竞争条件,您应该一步执行#1 和#2:

    {Pid, Ref} = spawn_monitor(?MODULE, loop [Sock]) 
  3. gen_tcp:accept(ListenSock) 执行后,做:

    gen_tcp:close(ListenSock)
  4. 检测客户端何时终止,因此是时候开始监听新客户端了:

    receive {'DOWN', Ref, process, Pid, _Reason} -> 
    listen(Ip, Port)

    或者,如果客户端在完成发送数据后不会终止,那么您可以在loop() 中检测客户端何时关闭套接字:

     case gen_tcp:recv(Sock, 0) of
    {ok, Data} ->
    gen_tcp:send(Sock, [<<"Response: ">>, Data]),
    ?MODULE:loop(Sock);

    {error, closed} ->
    listen(Ip, Port);

    {error, Reason} ->
    ok
    end

=====

backlog 套接字选项(例如 {backlog, 0}):

backlog 选项设置操作系统套接字配置参数。来自 man listen:

The backlog parameter defines the maximum length for the queue of pending connections. If a connection request arrives with the queue full, the client may receive an error with an indication of ECONNREFUSED. Alternatively, if the underlying protocol supports retransmission, the request may be ignored so that retries may succeed.

而且,Perl Monks 上的这个主题值得一读:TCP server: How to reject connections when busy?关于 backlog 配置的一些片段:

So, it looks like connection request are just ignored (as TCP does support retransmission)

...when the queue is full, then the system simply stops answering SYN packets, which triggers their resending. As result, the peer gets no indication that your server is busy. It simply keeps waiting for connection to be established.

关于tcp - 如何在 erlang gen_tcp 中同时处理一个客户端?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54522876/

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