[erlang] Erlang TCP(gen_tcp)

  1 -module(socket_example).
  2 -compile(export_all).
  3 
  4 nano_get_url() ->
  5     nano_get_url("www.google.com").
  6 
  7 nano_get_url(URL) ->
  8     {ok,Socket} = gen_tcp:connect(URL,80,[binary,{packet,0}]),
  9     ok = gen_tcp:send(Socket,"GET / HTTP/1.0\r\n\r\n"),
 10     receive_data(Socket,[]).
 11 
 12 receive_data(Socket,SoFar) ->
 13     receive
 14         {tcp,Socket,Bin} ->
 15             receive_data(Socket,[Bin|SoFar]);
 16         {tcp_closed,Socket} ->
 17             list_to_binary(lists:reverse(SoFar))
 18     end.
 19 
 20 start_nano_server() ->
 21     %% 返回 {ok,Socket} 或 error,Why
 22     case gen_tcp:listen(2345,[binary,{packet,4}, %% 每个应用程序消息都从一个4字节长的头部开始
 23                                        {reuseaddr,true},  %% 
 24                                        {active,true}]) of %% {active,true} 创建一个主动套字节(非阻塞) 
 25                                                              %% {active,false} 创建一个被动套字节(阻塞) 
 26                                                           %% {active,once} 创建一个主动套字节仅接收一条消息,如想接收下一条必须再次激活(半阻塞)
 27         {ok,Listen} ->
 28             case gen_tcp:accept(Listen) of %% 等待暂停并等待一个连接
 29                 {ok,Socket} ->
 30                     gen_tcp:close(Listen), %% 关闭监听,服务器不会继续处于监听状态,也无法建立任何新的连接 
 31                     loop(Socket);
 32                 {error,Why} ->
 33                     io:format("~p~n",[Why])
 34             end;
 35         {error,Why} ->
 36             io:format("~p~n",[Why])
 37     end.
 38 
 39 loop(Socket) ->
 40     receive
 41         {tcp,Socket,Bin} ->
 42             io:format("Server received binary = ~p~n",[Bin]),
 43             Str = binary_to_term(Bin),
 44             io:format("Server (unpacked) ~p~n",[Str]),
 45             Reply = Str,
 46             timer:sleep(5000),
 47             %%Reply = lib_misc:string2value(Str),
 48             io:format("Server replying = ~p~n",[Reply]),
 49             gen_tcp:send(Socket,term_to_binary(Reply)),
 50             loop(Socket);
 51         {tcp_closed,Socket} ->
 52             io:format("Server socket closed~n")
 53     end.
 54 
 55 nano_client_eval(Str) ->
 56     {ok,Socket} = gen_tcp:connect("localhost",2345,[binary,{packet,4}]),
 57     ok = gen_tcp:send(Socket,term_to_binary(Str)),
 58     receive
 59         {tcp,Socket,Bin} ->
 60             io:format("Client received binary = ~p~n",[Bin]),
 61             Val = binary_to_term(Bin),
 62             io:format("Client result = ~p~n",[Val]),
 63             gen_tcp:close(Socket)
 64     end.
 65 
 66 %% 顺序型服务器(一个服务器一次只接收一个连接)
 67 start_seq_server() ->
 68     case gen_tcp:listen(2345,[binary,{packet,4}, %% 每个应用程序消息都从一个4字节长的头部开始
 69                                        {reuseaddr,true},  %% 
 70                                        {active,true}]) of
 71         {ok,Listen} ->
 72             seq_loop(Listen);
 73         {error,Why} ->
 74             io:format("~p~n",[Why])
 75     end.
 76 
 77 seq_loop(Listen) ->
 78     case gen_tcp:accept(Listen) of %% 等待暂停并等待一个连接
 79         {ok,Socket} ->
 80             loop(Socket),
 81             seq_loop(Listen);
 82         {error,Why} ->
 83             io:format("~p~n",[Why])
 84     end.
 85 
 86 %% 并行服务器
 87 start_parallel_server() ->
 88     case gen_tcp:listen(2345,[binary,{packet,4}, %% 每个应用程序消息都从一个4字节长的头部开始
 89                                        {reuseaddr,true},  %% 
 90                                        {active,true}]) of
 91         {ok,Listen} ->
 92             spawn(fun()-> par_connect(Listen) end);
 93         {error,Why} ->
 94             io:format("~p~n",[Why])
 95     end.
 96 
 97 par_connect(Listen) ->
 98     case gen_tcp:accept(Listen) of %% 等待暂停并等待一个连接
 99         {ok,Socket} ->
100             spawn(fun() -> par_connect(Listen) end),
101             loop(Socket);
102         {error,Why} ->
103             io:format("~p~n",[Why])
104     end.

TCP服务器结果

server

Eshell V5.8.4  (abort with ^G)
1> c(socket_example).
{ok,socket_example}
2> socket_example:start_nano_server().
Server received binary = <<131,107,0,4,49,50,51,52>>
Server (unpacked) "1234"
Server replying = "1234"
Server socket closed
ok
>

client

Eshell V5.8.4  (abort with ^G)
1> c(socket_example).
{ok,socket_example}     
2> socket_example:nano_client_eval("1234").
Client received binary = <<131,107,0,4,49,50,51,52>>
Client result = "1234"

顺序服务器

server

Eshell V5.8.4  (abort with ^G)
1> socket_example:start_seq_server().
Server received binary = <<131,107,0,4,49,50,51,52>>
Server (unpacked) "1234"
Server replying = "1234"
Server socket closed
Server received binary = <<131,107,0,4,52,51,50,49>>
Server (unpacked) "4321"
Server replying = "4321"
Server socket closed

client1

Eshell V5.8.4  (abort with ^G)
1> socket_example:nano_client_eval("1234").
Client received binary = <<131,107,0,4,49,50,51,52>>
Client result = "1234"
ok
2>

client2

Eshell V5.8.4  (abort with ^G)
1> socket_example:nano_client_eval("4321").
Client received binary = <<131,107,0,4,52,51,50,49>>
Client result = "4321"
ok
2> 

并行服务器

server

Eshell V5.8.4  (abort with ^G)
1> socket_example:start_parallel_server().
<0.34.0>
Server received binary = <<131,107,0,4,49,50,51,52>>
Server (unpacked) "1234"
Server received binary = <<131,107,0,4,52,51,50,49>>
Server (unpacked) "4321"
Server replying = "1234"
Server socket closed
Server replying = "4321"
Server socket closed
2>

client1

Eshell V5.8.4  (abort with ^G)
1> socket_example:nano_client_eval("1234").
Client received binary = <<131,107,0,4,49,50,51,52>>
Client result = "1234"
ok
2>

client2

Eshell V5.8.4  (abort with ^G)
1> socket_example:nano_client_eval("4321").
Client received binary = <<131,107,0,4,52,51,50,49>>
Client result = "4321"
ok
2> 
原文地址:https://www.cnblogs.com/bluefrog/p/2511794.html