一个简单的TCP服务器

1.只接收一个连接然后自动关闭的服务端代码

 1 -module(socket_server).
 2 
 3 -export([start_nano_server/0]).
 4 
 5 start_nano_server() ->
 6     % 监听来自端口2345上的连接,消息打包规则{packet, 4} -> 每个应用程序都是从一个4字节长的头部开始
 7     % gen_tcp:listen -> {ok, ListenSocket} | {error, Reason}, ListenSocket为监听套接字 
 8     {ok, ListenSocket} = gen_tcp:listen(2345, [binary, {packet, 4},
 9                                         {reuseaddr, true},
10                                         {active, true}]),
11     % gen_tcp:accept(Listensocket)调用时,程序会暂停并等待一个连接
12     % 当一个新的连接建立起来时会返回变量Socket,该变量绑定到新建连接的套接字上
13     % 通过Socket套接字,服务器就可以和发起连接的客户机进行通信
14     {ok, Socket} = gen_tcp:accept(ListenSocket),
15     % 关闭监听套接字,此后服务器不会继续处于监听状态,也无法建立新的连接,但并不影响已经建立的连接套接字
16     % 只是阻止新连接的建立
17     gen_tcp:close(ListenSocket),
18     loop(Socket).
19 
20 loop(Socket) ->
21     receive
22         {tcp, Socket, Bin} ->
23             io:format("Server received binary = ~p~n", [Bin]),
24             Str = binary_to_term(Bin),  % 对接收数据解码(反整编)
25             io:format("Server(unpacked) ~p~n", [Str]),
26             Reply = lib_misc:string2value(Str),     % 对回应数据进行编码(整编)
27             io:format("Server replying = ~p~n", [Reply]),
28             % send(Socket, Packet) -> ok | {error, Reason}, Packet -> iodata()
29             gen_tcp:send(Socket, term_to_binary(Reply)),
30             loop(Socket);
31         {tcp_closed, Socket} ->
32             io:format("Server socket closed~n")
33     end.

2.顺序型服务器

 1 %% 顺序型服务器
 2 -module(socket_server_order).
 3 
 4 -export([start_nano_server/0]).
 5 
 6 start_nano_server() ->
 7     % 监听来自端口2345上的连接,消息打包规则{packet, 4} -> 每个应用程序都是从一个4字节长的头部开始
 8     % gen_tcp:listen -> {ok, ListenSocket} | {error, Reason}, Listen为监听套接字 
 9     {ok, ListenSocket} = gen_tcp:listen(2345, [binary, {packet, 4},
10                                         {reuseaddr, true},
11                                         {active, true}]),
12     req_loop(ListenSocket).
13 
14 req_loop(ListenSocket) ->
15     {ok, Socket} = gen_tcp:accept(ListenSocket),
16     loop(Socket),
17     req_loop(ListenSocket).
18 
19 loop(Socket) ->
20     receive
21         {tcp, Socket, Bin} ->
22             io:format("Server received binary = ~p~n", [Bin]),
23             Str = binary_to_term(Bin),
24             io:format("Server(unpacked) ~p~n", [Str]),
25             Reply = lib_misc:string2value(Str),
26             io:format("Server replying = ~p~n", [Reply]),
27             gen_tcp:send(Socket, term_to_binary(Reply)),
28             loop(Socket);
29         {tcp_closed, Socket} ->
30             io:format("Server socket closed~n")
31     end.

3.并发型服务器

 1 %% 并发型服务器
 2 -module(socket_server_order).
 3 
 4 -export([start_nano_server/0]).
 5 
 6 start_nano_server() ->
 7     % 监听来自端口2345上的连接,消息打包规则{packet, 4} -> 每个应用程序都是从一个4字节长的头部开始
 8     % gen_tcp:listen -> {ok, ListenSocket} | {error, Reason}, Listen为监听套接字 
 9     {ok, ListenSocket} = gen_tcp:listen(2345, [binary, {packet, 4},
10                                         {reuseaddr, true},
11                                         {active, true}]),
12     spawn(fun() -> par_connect(ListenSocket) end).
13 
14 par_connect(ListenSocket) ->
15     {ok, Socket} = gen_tcp:accept(ListenSocket),
16     spawn(fun() -> par_connect(ListenSocket) end),
17     loop(Socket).
18 
19 loop(Socket) ->
20     receive
21         {tcp, Socket, Bin} ->
22             io:format("Server received binary = ~p~n", [Bin]),
23             Str = binary_to_term(Bin),
24             io:format("Server(unpacked) ~p~n", [Str]),
25             Reply = lib_misc:string2value(Str),
26             io:format("Server replying = ~p~n", [Reply]),
27             gen_tcp:send(Socket, term_to_binary(Reply)),
28             loop(Socket);
29         {tcp_closed, Socket} ->
30             io:format("Server socket closed~n")
31     end.

4.客户端代码

 1 -module(socket_client).
 2 
 3 -export([nano_client_eval/1]).
 4 
 5 nano_client_eval(Str) ->
 6     {ok, Socket} = gen_tcp:connect("localhost", 2345,
 7                                     [binary, {packet, 4}]),
 8     ok = gen_tcp:send(Socket, term_to_binary(Str)),
 9     receive
10         {tcp, Socket, Bin} ->
11             io:format("Client received binary = ~p~n", [Bin]),
12             Val = binary_to_term(Bin),
13             io:format("Client result = ~p~n", [Val]),
14             gen_tcp:close(Socket)
15     end.

5.lib_misc模块

1 -module(lib_misc).
2 
3 -export([string2value/1]). 
4 
5 string2value(L) -> string2value(L, []).
6 string2value([], N)    -> list_to_tuple(lists:reverse(N));
7 string2value([H|T], N) -> string2value(T, [H|N]).

 6.测试

  6.1只接收一个连接然后自动关闭的服务端代码测试

 

  6.2顺序型服务器测试

 

 6.3并发型测试

 

ps:顺序型服务器相对并发型服务器的区别在于:顺序型服务器忙于服务一个现存的连接时,如果又有新的客户机尝试连接服务器,那么这个连接就会在服务器排队,直到服务器完成对现有的服务为止,如果等待队列中的连接数目超过了监听套接字的能力,那么这个连接就会被拒绝,而并发型服务器则不会有该问题

转载于:https://www.cnblogs.com/huangxiaoyi/p/5709588.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值