前面学习完了gen_server 、gen_tcp 现在做一个简易的socket通讯,服务端将接收到的信息返回给客户端,具体代码如下:
服务端:
1 -module(tcp_socket3). 2 -behaviour(gen_server). 3 4 -export([start/0, login/2, stop/0]). 5 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). 6 7 -export([start_client/0]). 8 9 -record(users, {id, name, pwd}). 10 11 start() -> 12 start(6000). 13 14 start(Port) -> 15 gen_server:start_link({local, ?MODULE}, ?MODULE, [], []), 16 {ok, ListenSocket} = gen_tcp:listen(Port, [binary,{packet, 0}, {active, true}]), 17 par_connect(ListenSocket). 18 19 init([]) -> 20 ets:new(?MODULE, [set, public, named_table, {keypos, #users.id}]), 21 22 {ok, ?MODULE}. 23 24 par_connect(Listen) -> 25 {ok, Socket} = gen_tcp:accept(Listen), 26 spawn(fun() -> par_connect(Listen) end), 27 loop(Socket). 28 29 loop(Socket) -> 30 receive 31 {tcp, Socket, Data} -> 32 io:format("Server receive binary:~p~n", [Data]), 33 RecStr = binary_to_list(Data), 34 io:format("Server receive binary_to_list:~p~n",[RecStr]), 35 gen_tcp:send(Socket, Data), 36 loop(Socket); 37 {tcp_closed, Socket} -> 38 io:format("Client socket closed") 39 end. 40 41 42 login(Id,Pwd) -> 43 gen_server:call(?MODULE,{login, Id, Pwd}). 44 45 stop() -> 46 gen_server:call(?MODULE, stop). 47 48 handle_call({login, Id, Pwd}, _From, Tab) -> 49 Reply = case ets:lookup(Tab, Id) of 50 [] -> User1=#users{id=Id, name=Id, pwd=Pwd}, 51 ets:insert(Tab, User1), 52 io:format("Tab content:~p~n",[ets:tab2list(Tab)]) 53 end, 54 {reply, Reply, Tab}; 55 handle_call(stop, _From, Tab) -> 56 {stop, normal, stopped, Tab}. 57 58 handle_cast(_Msg, State) -> {noreply, State}. 59 handle_info(_Info, State) -> {noreply, State}. 60 terminate(_Reason, State) -> 61 ok. 62 63 code_change(_OldVsn, State, _Extra) -> {ok, State}. 64 65 start_client() -> 66 start_client("localhost", 6000). 67 68 start_client(Address, Port) -> 69 {ok, Socket} = gen_tcp:connect(Address, Port, [binary, {packet, 0}, {active, true}]), 70 ok=gen_tcp:send(Socket, list_to_binary("{login,tom, tom1}")), 71 receive 72 {tcp, Socket, Data} -> 73 io:format("Client receive binary:~p~n", [Data]), 74 RecStr = binary_to_list(Data), 75 io:format("Client receive binary_to_list:~p~n", [RecStr]), 76 gen_tcp:close(Socket) 77 end.
客户端:
1 -module(tcp_client). 2 -behaviour(gen_server). 3 4 -export([start/0, start/2, stop/0, send_data/1]). 5 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). 6 7 -define(HOSTIP,"127.0.0.1"). 8 -define(PORT, 8000). 9 10 -record(state, {socket}). 11 12 start() -> 13 start(?HOSTIP, ?PORT). 14 15 start(HOSTIP, PORT) -> 16 gen_server:start_link({local, ?MODULE}, ?MODULE,[HOSTIP, PORT], []). 17 18 init([HostIP, Port]) -> 19 case gen_tcp:connect(HostIP, Port, [binary, {packet, 0}, {active, true}]) of 20 {ok, Socket} -> 21 io:format("Connect host success, start to receive message:~n"), 22 spawn(fun() ->loop(Socket) end), 23 {ok, #state{socket = Socket}}; 24 {error, Reason} -> 25 io:format("Connect host error:~p~n", [Reason]), 26 {stop, Reason} 27 end. 28 29 30 loop(Socket) -> 31 io:format("loop start ~n"), 32 receive 33 {tcp, Socket, Data} -> 34 io:format("Client receive binary:~p~n", [Data]), 35 loop(Socket); 36 {tcp_closed, Socket} -> 37 io:format("Client is closed~n"), 38 stop() 39 end. 40 41 stop() -> 42 gen_server:cast(?MODULE, stop). 43 44 send_data(Msg) -> 45 gen_server:call(?MODULE,Msg). 46 47 handle_call(Msg, _From, State) -> 48 Reply = gen_tcp:send(State#state.socket, list_to_binary(Msg)), 49 {reply,Reply, State}. 50 handle_cast(stop, State) -> 51 {stop, normal, State}. 52 handle_info({tcp,Socket, RawData}, State) -> 53 io:format("Client receive msg:~p~n", [RawData]), %% 处理接收到的信息 54 {noreply, State}; 55 handle_info({tcp_closed, _Socket}, State) -> 56 stop(), 57 {noreply, State}. 58 terminate(_Reason, _State) -> 59 ok. 60 code_change(_OldVsn, State, Extra) -> 61 {ok, State}.
运行服务端:
2> c(tcp_socket3). tcp_socket3.erl:60: Warning: variable 'State' is unused {ok,tcp_socket3} 3> tcp_socket3:start(). Server receive binary:<<"abcdaeafad">> Server receive binary_to_list:"abcdaeafad"
运行客户端:
8> tcp_client:start("127.0.0.1", 6000). Connect host success, start to receive message: loop start {ok,<0.52.0>} 9> tcp_client:send_data("abcdaeafad"). ok Client receive msg:<<"abcdaeafad">>