如何使用gen_sctp:send / 3

时间:2016-12-07 07:19:27

标签: sockets erlang sctp

我在服务器 - 客户端模型中使用 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回复客户端消息?

谢谢和最诚挚的问候,

陈。

1 个答案:

答案 0 :(得分:0)

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记录类型,而gen_sctp:send / 4仅为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().