版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qqqrtretretee/article/details/76863101
erlang语言实现socket聊天室
关键词
erlang
socket
erlang语言是函数式编程语言,由Erlang之父Joe Amstrong编写出erlang原型,并在爱立信公司得到大规模应用,进而在通信行业有了一席之地,其优势在于高并发性、容错、高性能。
socket是实现数据交互的最普遍的方式,Erlang/OTP中也融合了tcp协议,并通过OTP中的库简单的编程就能实现服务端、客户端的通信,现在我们自己来实现编写服务器和客户端。
什么都不多说了,先上菜再解释
- 服务器端
-module (server).
-export ([start/0]).
-define (tcp_opts, [binary, {active,true}, {packet, 0},{reuseaddr, true}]).
%% 宏定义,当代码读到?errorlog,会用io:format("errorlog point")代替
-define (errorlog, io:format("errorlog point~n")).
start() ->
start(8888).
start(Port) ->
{ok, ListenSocket} = gen_tcp:listen(Port, ?tcp_opts),
register(server, spawn(fun() -> server_conn(ListenSocket) end)),
server_conn(ListenSocket).
server_conn(ListenSocket) ->
case gen_tcp:accept(ListenSocket) of
{ok, Socket} ->
io:format("connect succeed:~p~n",[Socket]),
server_route();
{error, Reason} ->
io:format("Socket closed : ~p~n",[Reason])
end.
server_route() ->
receive
{tcp, Socket, Data} ->
?errorlog,
gen_tcp:send(Socket, Data);
{tcp_closed, Socket} ->
gen_tcp:close(Socket)
end.
- 客户端
-module (client).
-export ([start/0]).
-define (tcp_opts, [binary, {packet, 0},{active, true}]).
start() ->
start("localhost",8888).
start(IP,Port) ->
register(client, spawn(fun() -> conn_client(IP,Port) end)).
conn_client(IP,Port) ->
case gen_tcp:connect(IP, Port, ?tcp_opts) of
{ok, Socket} ->
send_msg(Socket),
do_handle_client(Socket),
io:format("connection successed! ~w~n",[Socket]),
conn_client(IP,Port);
{error, Reason} ->
io:format("connect failed! ~n"),
exit(Reason)
end.
do_handle_client(Socket) ->
receive
{tcp, Socket, Packet} ->
recv_msg(Packet),
do_handle_client(Socket);
{tcp_closed, Socket} ->
gen_tcp:close(Socket)
end.
recv_msg(Packet) ->
Msg= binary_to_term(Packet),
io:format("Received Msg: ~p~n", [Msg]).
send_msg(Socket) ->
Msg = io:get_line('Input Your Msg:'),
Pack = term_to_binary(Msg),
io:format("Your msg: ~p~n", [Msg]),
gen_tcp:send(Socket, Pack),
send_msg(Socket).
在服务端中定义了start函数并把端口Port绑定为8888(和客户端对应端口),在第三步用gen_tcp模块的accept函数返回一个Socket进程(Java是说实例化了一个socket),接着在请求连接的下一个函数定义了接收进程(注意:register中启动了一个进程,这个就是接收进程),然后按照这些步骤定义之后,在Erlang shell打印输出:
服务端(要启动两个窗口,one for server,another for client)
1>server:start().
客户端
1>client:start().
运行结果如下所示: