Erlang--TCP学习(二)简单web_Server篇

  现在来写个简单的web服务器,要实现的功能是:只接受一个socket连接请求。

服务器代码:tcp_server.erl
-module(tcp_server).

-compile(export_all).

-define(TCP_OPT, [binary, {packet, 4}, {reuseaddr,true}, {active, true}]).

%% binary 设置通信数据格式,可以通过简单的term_to_binary编码, binary_to_term解码
%% {packet, 4} 每个报文从一个4字节长的头开始
%% {reuseaddr, true} 端口复用
%% {active, true} 主动套接字(非阻塞)
%% {active,false} 被动套接字(阻塞)
%% {active,once}  主动套接字仅接受一条信息,要想接受下一条必须再次激活(半阻塞)

start_server() ->
    {ok, ListenSocket} = gen_tcp:listen(8888, ?TCP_OPT), %% 监听8888端口
    io:format(" listen socket :~p~n", [ListenSocket]),
    {ok, Socket} = gen_tcp:accept(ListenSocket), %% 程序挂起,等待连接
    io:format(" accept socket :~p~n", [Socket]),
    gen_tcp:close(ListenSocket),%% 关闭监听,服务器无法再建立新的连接
                                 %% 不影响已有的socket通信
    loop(Socket).

loop(Socket) ->
    receive
        {tcp, Socket, Bin} ->
             io:format("receive bin data: ~p~n",[Bin]),
             Str = binary_to_term(Bin),
             io:format("unpack data: ~w~n",[Str]),
             Reply = {9999,9999000},
             io:format("server reply: ~p~n", [Reply]),
             gen_tcp:send(Socket, term_to_binary(Reply)),
             loop(Socket);
        {tcp_closed, Socket} ->
             io:format("socket closed: ~p~n",[Socket])
    after 3000 -> %% 超时关闭socket
             gen_tcp:close(Socket)
    end.


客户端代码:tcp_client.erl
-module(tcp_client).

-export([test_tcp/0]).

test_tcp() ->
    {ok, Socket} = gen_tcp:connect("localhost", 8888, [binary, {packet, 4}]),
    io:format("listen socket:~p~n",[Socket]),
    SendData = term_to_binary({10,12}),
    Data2 = term_to_binary({56,12}), %% 发送了两次数据,是为了验证:
                                     %% 服务端关闭了listensocket,并不影响已有的socket
    ok = gen_tcp:send(Socket, SendData),
    ok = gen_tcp:send(Socket, Data2),
    loop(Socket).

loop(Socket) ->
    receive
        {tcp, Socket, Bin} ->
             io:format("receive bin data: ~p~n",[Bin]),
             Val = binary_to_term(Bin),
             io:format("receive data: ~p~n",[Val]),
             loop(Socket);
        {tcp_closed, Socket} ->
              io:format("socket closed :~p~n",[Socket])
    end.


执行服务端代码:
erlc tcp_server.erl
erl
tcp_server:start_server().


执行客户端代码:
erlc tcp_client.erl
erl
tcp_client:test_tcp().


服务端结果:


客户端结果:

猜你喜欢

转载自room-bb.iteye.com/blog/2227269
今日推荐