现在来写个简单的web服务器,要实现的功能是:只接受一个socket连接请求。
服务器代码:tcp_server.erl
客户端代码:tcp_client.erl
执行服务端代码:
执行客户端代码:
服务端结果:
[img]http://dl2.iteye.com/upload/attachment/0110/1522/f96e9a35-a52e-369c-9513-ea9dbef47adc.png[/img]
客户端结果:
[img]http://dl2.iteye.com/upload/attachment/0110/1525/3af9df42-9af8-3fc4-b760-04d88622b3d8.png[/img]
服务器代码: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().
服务端结果:
[img]http://dl2.iteye.com/upload/attachment/0110/1522/f96e9a35-a52e-369c-9513-ea9dbef47adc.png[/img]
客户端结果:
[img]http://dl2.iteye.com/upload/attachment/0110/1525/3af9df42-9af8-3fc4-b760-04d88622b3d8.png[/img]