Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4995450
  • 博文数量: 921
  • 博客积分: 16037
  • 博客等级: 上将
  • 技术积分: 8469
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 02:08
文章分类

全部博文(921)

文章存档

2020年(1)

2019年(3)

2018年(3)

2017年(6)

2016年(47)

2015年(72)

2014年(25)

2013年(72)

2012年(125)

2011年(182)

2010年(42)

2009年(14)

2008年(85)

2007年(89)

2006年(155)

分类:

2013-01-01 15:33:40

erlang服务端,主要实现与flash客户端的连接、消息传递服务
自带843端口服务解决flash9以上暴汗的安全沙箱问题

chat.erl

  1. -module(chat).
  2. -export([start/0,manage_clients/1,stop/0,find/1]).
  3. -record(player, {id,socket,time=none}).

  4. start() ->
  5.         chat_server:start(?MODULE,manage_clients).

  6. stop()->
  7.         chat_server:stop(?MODULE),
  8.         timer:sleep(2000), %%等待所有连接断开
  9.         manage_clients!{exit}.

  10. manage_clients(Players) ->
  11.         receive
  12.             {connect, Socket} ->
  13.                 Player = #player{
  14.                         id="guest_"++integer_to_list(random:uniform(100000)),
  15.                         socket=Socket,
  16.                         time=time()
  17.                         }, %%新增记录
  18.                 io:fwrite("Socket connected: ~w~n", [Socket]),
  19.                 NewPlayers = [Player|Players]; %%累加到列表

  20.             {disconnect, Socket} ->
  21.                 io:fwrite("Socket disconnected: ~w~n", [Socket]),
  22.                 Player = find_Socket(Socket, Players), %%查找socket对应的记录
  23.                 NewPlayers = lists:delete(Player, Players); %%删除记录

  24.             {chat,Data} ->
  25.                 send_data(Players, Data),
  26.                 NewPlayers=Players;

  27.             {list,Uname}->
  28.                 find_player(Uname,Players),
  29.                 NewPlayers = Players;

  30.             {exit}->
  31.                 NewPlayers="",
  32.                 exit({stop, exit})
  33.         end,
  34.         manage_clients(NewPlayers).





  35. %%对客户端进行广播
  36. send_data(Players, Data) ->
  37.   SendData = fun(Player) ->
  38.     gen_tcp:send(Player#player.socket, Data)
  39.   end,
  40.   lists:foreach(SendData, Players).

  41. %%查找指定记录
  42. find_Socket(Socket, Players) ->
  43.     {value, Player} = lists:keysearch(Socket, #player.socket, Players),
  44.     Player.

  45. find_player(Uname, Players) ->
  46.     case lists:keysearch(Uname, #player.id, Players) of
  47.     {value, Player}->
  48.         io:fwrite("Find a player: ~w~n", [Player]);
  49.     _->io:fwrite("No found.~n")
  50.     end.


  51. %%查找用户
  52. find(Uname)->
  53.         client_manager ! {list,Uname}.

chat_server.erl

  1. -module(chat_server).
  2. -behaviour(gen_server).
  3. -export([start/2,stop/1]).

  4. %% gen_server回调
  5. -export([init/1,handle_call/3,handle_cast/2,handle_info/2,
  6.         terminate/2,code_change/3]).
  7. -compile(export_all).

  8. -define(TCP_OPTIONS, [list, {packet, 0}, {active, false}, {reuseaddr, true},{nodelay, false},{delay_send, true}]).
  9. %%状态表
  10. -record(state, {name,loop,socket}).

  11. %%回调gen_server创建服务
  12. start(Name,Loop) ->
  13.         State=#state{name=Name,loop=Loop}, %%定为记录
  14.         gen_server:start_link({local,Name},?MODULE,State,[]).


  15. %%start() ->
  16. %% gen_server:start_link({local,?MODULE},?MODULE,[],[]).


  17. %%停止服务
  18. stop(Name) ->
  19.         gen_server:call(Name,stop).


  20. init(State) ->
  21.         %%维护队列 chat.rar (17.12 KB, 下载次数: 379) 2009-12-15 20:04 上传下载次数: 379

  22.         register(State#state.loop, spawn(fun() -> (State#state.name):(State#state.loop)([]) end)),
  23.         {Tag, LSocket}=gen_tcp:listen(8080, ?TCP_OPTIONS), %%默认8080
  24.         case Tag of %%创建监听
  25.                 ok -> spawn(fun() -> do_accept(State#state{socket=LSocket}) end); %%统一接收
  26.                 error -> exit({stop, exit}) %%出错,退出连接
  27.         end,
  28.                                 
  29.         %%与flash通信的安全策略文件传送监听接口
  30.         {Req, AsSocket}=gen_tcp:listen(843, ?TCP_OPTIONS),
  31.         case Req of
  32.                 ok -> spawn(fun() -> do_accept2(AsSocket) end);
  33.                 error -> exit({stop, exit})
  34.         end,
  35.         {ok,LSocket}.

  36. handle_call(stop,_From,Tab) ->
  37.         {stop,normal,stopped,Tab}.


  38. handle_cast(stop,State) ->{stop, normal, State};
  39. handle_cast(_Msg,State) ->{noreply,State}.
  40. handle_info(_Info,State) ->{noreply,State}.
  41. terminate(_Reason,_State) ->ok.
  42. code_change(_OldVsn,State,_) ->{ok,State}.







  43. %% -----------------------------------
  44. %% -------------私有函数--------------
  45. %% -----------------------------------



  46. %%新建连接,只有新连接时才调用
  47. do_accept(State) ->
  48.         case gen_tcp:accept(State#state.socket) of
  49.                 {ok, Socket}->
  50.                         %%创建进程处理响应
  51.                         spawn(fun() -> handle_client(State,Socket) end),
  52.                         %%创建新连接,持久化
  53.                         State#state.loop ! {connect, Socket},
  54.                         do_accept(State);
  55.                 _->
  56.                         ok
  57.         end.



  58. %%处理flash安全策略文件的发送服务
  59. do_accept2(LSocket) ->
  60.         case gen_tcp:accept(LSocket) of
  61.                 {ok, Socket}->
  62.                         spawn(fun() -> put_file(Socket) end),
  63.                         do_accept2(LSocket);
  64.                 _->ok
  65.         end.

  66. %%短连接策略,连接完关闭
  67. put_file(Socket)->
  68.           case gen_tcp:recv(Socket, 0) of
  69.                 {ok, _} ->
  70.                         %%判断数据返回策略文件
  71.                         gen_tcp:send(Socket, "
  72.                 
  73.                 
  74.                 \0");
  75.                 {error, closed} ->ok
  76.           end,
  77.           gen_tcp:close(Socket). %%关闭连接




  78. handle_client(State,Socket) ->
  79.           case gen_tcp:recv(Socket, 0) of
  80.                 {ok, Data} ->
  81.                         State#state.loop ! {chat, Data},
  82.                         handle_client(State,Socket);
  83.                 {error, closed} ->
  84.                         State#state.loop ! {disconnect, Socket}
  85.           end.


简单的flash客户端,为as3代码:


 

  1. package
  2. {
  3.         import flash.net.Socket;
  4.         import flash.display.Sprite;
  5.         import flash.events.*;
  6.         import flash.text.TextField;

  7.         [SWF(width=600, height=300)]
  8.         public class chat extends Sprite
  9.         {
  10.                 private var textArea:TextField;
  11.                 private var input:TextField;
  12.                 private var label:TextField;
  13.                 private var socket:Socket=new Socket();

  14.                 public function chat()
  15.                 {
  16.                         socket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
  17.                         socket.connect("192.168.10.112", 8080); //连接到服务端,这里改成服务端的IP和端口

  18.                         socket.flush();

  19.                         initUI();
  20.                         input.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler); //按回车响应

  21.                         textArea.addEventListener(Event.RENDER, renderHandler);
  22.                 }
  23.                 
  24.                 private function sendMsg(Msg:String):void
  25.                 {
  26.                         socket.writeUTFBytes(Msg);
  27.                         socket.flush();
  28.                 }
  29.                 
  30.                 private function keyDownHandler(e:KeyboardEvent):void
  31.                 {
  32.                         if (13 == e.charCode)
  33.                         {
  34.                                 var s:String = input.text ? input.text : "null";
  35.                                 input.text = "";
  36.                                 sendMsg(s);
  37.                         }
  38.                 }
  39.                 
  40.                 private function renderHandler(e:Event):void
  41.                 {
  42.                         textArea.scrollV = textArea.maxScrollV;
  43.                 }
  44.                 
  45.                 
  46.                 //初始化

  47.                 private function initUI():void
  48.                 {
  49.                         textArea = new TextField();
  50.                         textArea.width = 400;
  51.                         textArea.height = 150;
  52.                         textArea.border = true;
  53.                         textArea.x = 100;
  54.                         textArea.y = 30;
  55.                         addChild(textArea);
  56.                         
  57.                         input = new TextField();
  58.                         input.height = 20;
  59.                         input.width = 350;
  60.                         input.type = "input";
  61.                         input.border = true;
  62.                         input.multiline = false;
  63.                         input.x = 100;
  64.                         input.y = 200;
  65.                         addChild(input);
  66.                         
  67.                         label = new TextField();
  68.                         label.text = "回车发送";
  69.                         label.height = label.textHeight + 4;
  70.                         label.width = label.textWidth + 4;
  71.                         label.mouseEnabled = false;
  72.                         label.x = 460;
  73.                         label.y = 200;
  74.                         addChild(label);
  75.                 }

  76.                 
  77.                 // 事件处理回调函数,显示到屏幕上

  78.                 private function onSocketData(event:ProgressEvent):void
  79.                 {
  80.                         while (socket.bytesAvailable)
  81.                         {
  82.                                 var s:String = socket.readUTFBytes(socket.bytesAvailable);
  83.                                 if (textArea.text) s = "\n" + s;
  84.                                 textArea.appendText(s);
  85.                                 stage.invalidate();
  86.                         }
  87.                 }
  88.         }
  89. }


运行


 

  1. 1> c(chat).
  2. {ok,chat}
  3. 2> c(chat_server).
  4. {ok,chat_server}
  5. 3> chat:start().
  6. {ok,<0.435.0>}
  7. .....
  8. n> chat:stop().
  9. {exit}

附件: chat.rar   

文章来自:


 

阅读(1805) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~