如何使用 gen_sctp:send/3

how to use gen_sctp:send/3

我正在使用 gen_sctp 在服务器-客户端模型中创建 soscket 和关联时做一个例子。

在服务器端:

{ok,serverSocket} = gen_sctp:open(1234,[{ip,{127,0,0,1}},{reuseaddr,true},{active,true}]).

ok = gen_sctp:listen(S,true).

在客户端:

{ok,Client} = gen_sctp:open(1243,[{ip,{127,0,0,1}},{reuseaddr,true}]).

{ok,Ass} =  gen_sctp:connect(S,{127,0,0,1},1234,[{active,true}]).

然后客户端通过send/4:

向服务器发送消息
gen_sctp:send(S,Ass,2,<<"hellooooo">>).

服务器端接收消息:

{sctp,#Port<0.6126>,
                {127,0,0,1},
                1243,
                {[{sctp_sndrcvinfo,2,1,[],0,0,0,1409953138,0,18}],
                 <<"hellooooo">>}}

那么服务器如何才能通过send/3向客户端回复消息呢?

谢谢并致以最诚挚的问候,

翻译

gen_sctp:send/3 类似于 gen_sctp:send/4 但您可以设置更多标志和选项。您已经在客户端代码中使用了 gen_sctp:send/4(当您弄乱了客户端和服务器套接字时):

{ok, Assoc} = gen_sctp:connect(ClientSocket, {127,0,0,1}, 1234,[{active,true}]).
gen_sctp:send(ClientSocket, Assoc, 2, <<"hellooooo">>).

Assoc 属于 sctp_assoc_change record type while gen_sctp:send/4 looks just for assoc_id if you provide sctp_assoc_change。因此,目前提供 #sctp_assoc_change{} 或只是关联 ID 的行为完全相同。

以及如何在服务器中找到客户端的关联ID?它在服务器收到的消息中提供:

{sctp,#Port<0.6126>,
                {127,0,0,1},
                1243,
                {[{sctp_sndrcvinfo,2,1,[],0,0,0,1409953138,0,18}],
                 <<"hellooooo">>}}

#sctp_sdnrcvinfo{} 记录有字段告诉关联 ID 和从哪个数据接收的流编号。您可以从 assoc_id 字段获取当前关联 ID 并将其传递给另一个 gen_sctp:send/4:

gen_sctp:send(ServerSocket, AssocID, 2, <<"welcome!">>).

流编号为 2 可能不会使其失败,因为默认情况下 gen_sctp:open 生成 10 个传入和传出流,但您可以安全地提供 0 作为流编号。

下面是一个用sctp发送和接收数据的例子:

#!/usr/bin/escript

-include_lib("kernel/include/inet_sctp.hrl").   

server_loop(Socket) ->
  receive
    {sctp, Socket, _FromIP, _FromPort, {[#sctp_sndrcvinfo{assoc_id=AssocID}],
                                        Payload}} ->
      gen_sctp:send(Socket, #sctp_sndrcvinfo{assoc_id=AssocID, stream=0},
                    <<"pong">>),
      % or less complex gen_sctp:send/4
      gen_sctp:send(Socket, AssocID, 0, <<"pong">>);
    Rest ->
      io:format("server got unhandled message ~w~n", [Rest])
  end,
  server_loop(Socket).

create_server_socket() ->
  {ok, Socket} = gen_sctp:open(1234, [{ip,{127,0,0,1}}, {reuseaddr,true},
                                      {active,true}]),
  gen_sctp:listen(Socket, true),
  {ok, Socket}.

run_server() ->
  Spawner = self(),
  spawn_link(fun() ->
    {ok, Socket} = create_server_socket(), Spawner ! ready, server_loop(Socket)
  end),
  receive
    ready ->
      io:format("server is up~n"),
      ok
    after 100 ->
      throw(server_timeout)
  end.

ping_server() ->
  {ok, Socket} = gen_sctp:open(1243, [{ip,{127,0,0,1}}, {reuseaddr, true}]),
  {ok, AssocChange} = gen_sctp:connect(Socket, {127,0,0,1}, 1234, [{active, true}]),
  gen_sctp:send(Socket, AssocChange, 2, <<"ping">>),
  receive
    {sctp, Socket, _FromIP, _FromPort, {[#sctp_sndrcvinfo{}], Payload}} ->
      io:format("client got payload ~p~n", [Payload])
    after 2000 ->
      throw(client_timeout)
  end.

main([]) ->
    run_server(),
    ping_server().