Chinaunix首页 | 论坛 | 博客
  • 博客访问: 48820
  • 博文数量: 9
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 92
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-27 19:21
文章分类

全部博文(9)

文章存档

2014年(9)

我的朋友

分类: 其他平台

2014-09-14 11:45:23

erlang服务端 quick_server.erl:

-module(quick_server).

-export([
   start/0,
  
   start_accepters/2,
   server_accept/2,
  
   client_loop/2,
  
   test_connect/0,
   send_login/2
  ]).

-define(PORT, 8888).

-define(MSG_ECHO(F,D), io:format("MODULE: ~p LINE: ~p PID: ~p  " ++ F, [?MODULE, ?LINE, self()|D])).


start() ->
 start(?PORT).

start(Port) ->
 Num = erlang:system_info(schedulers),
 case gen_tcp:listen(Port, [binary, {active, false}, {packet, 0}]) of
  {ok, LSock} ->
   register(?MODULE, spawn(?MODULE, start_accepters, [LSock, Num])),
   {ok, self()};
  {error, Reason} ->
   {error, Reason}
 end.
 
start_accepters(_, 0) ->
 server_loop([]);
start_accepters(LSock, Num) ->
 spawn(?MODULE, server_accept, [LSock, Num]),
 start_accepters(LSock, Num - 1).
 
server_loop(Clients) ->
 ?MSG_ECHO("now Clients: ~p~n", [Clients]),
 receive
  {login, Socket, Uid, Uname} ->
   case lists:keyfind(Socket, 1, Clients) of
    false ->
     ?MSG_ECHO("receive login Uid: ~p Uname: ~p~n", [Uid, Uname]),
     LoginData = msg_login(Uid, Uname),
     OnlinesData = msg_onlines(Clients),
     gen_tcp:send(Socket, OnlinesData),
     do_broadcast(Clients, LoginData),
     server_loop([{Socket, Uid, Uname}|Clients]);
     _ ->
     server_loop(Clients)
   end;
  {logout, Socket} ->
   case lists:keytake(Socket, 1, Clients) of
    {value, {Socket, Uid, _Uname}, NewClients} ->
     ?MSG_ECHO("receive logout Uid: ~p~n", [Uid]),
     LogoutData = msg_logout(Uid),
     do_broadcast(NewClients, LogoutData),
     server_loop(NewClients);
    false ->
     server_loop(Clients)
   end
 end.
 
server_accept(LSock, Num) ->
 erlang:process_flag(scheduler, Num),
 server_accept_acc(LSock, Num).
 
server_accept_acc(LSock,Num) ->
 case gen_tcp:accept(LSock) of
  {ok, CSock} ->
   Pid = spawn(?MODULE, client_loop, [CSock, Num]),
   gen_tcp:controlling_process(CSock, Pid),
   server_accept_acc(LSock, Num);
  Other ->
   io:format("accept has a error: ~w !~n", [Other]),
   server_accept_acc(LSock, Num)
 end.
 
client_loop(CSock, Num) ->
 erlang:process_flag(scheduler, Num),
 client_loop_acc(CSock, <<>>).
 
client_loop_acc(CSock, Bin) ->
 ?MSG_ECHO("loop Bin: ~p~n", [Bin]),
 inet:setopts(CSock, [{active, once}]),
 receive
  {tcp, CSock, SocketBin} ->
   ?MSG_ECHO("receive SocketBin: ~p~n", [SocketBin]),
   NewBin = work(<>, CSock),
   client_loop_acc(CSock, NewBin);
  {tcp_closed, CSock} ->
   ?MODULE ! {logout, CSock},
   io:format("socket ~w closed [~w]~n", [CSock, self()])
 end.
 
work(<>, CSock) ->
 check(BinData, CSock),
 work(Bin, CSock);
work(Bin, _CSock) ->
 Bin.
 
 
check(<>, CSock) ->
 ?MSG_ECHO("ProtocolCode: ~p~n", [ProtocolCode]),
 gateway(ProtocolCode, Bin, CSock).
 

% 登陆 Uid: 4 byte, UnameLen: 2 byte, Uname: string(UnameLen byte)
gateway(1001, <>, CSock) ->
 ?MODULE ! {login, CSock, Uid, Uname};
gateway(_Code, _Binary, _CSock) ->
 ?MSG_ECHO("ERROR msg, _Code: ~p _Binary: ~p~n", [_Code, _Binary]).
 

do_broadcast(Clients, BinData) ->
 [ gen_tcp:send(Socket, BinData) || {Socket, _Uid, _Uname} <- Clients].
 

msg_login(Uid, Uname) ->
 BinData = msg_user_base(Uid, Uname),
 msg(1002, BinData).
 
msg_onlines(Clients) ->
 Count = length(Clients),
 Fun = fun({_Socket, Uid, Uname}, AccBin) ->
    Fbin = msg_user_base(Uid, Uname),
    <>
    end,
 BinData = lists:foldl(Fun, <>, Clients),
 msg(1003, BinData).
 
msg_logout(Uid) ->
 BinData = <>,
 msg(1004, BinData).

msg_user_base(Uid, Uname) ->
 UnameLen = byte_size(Uname),
 <>.
 
msg(MsgCode, BinData1) ->
 BinLen = byte_size(BinData1) + 2,
 BinData = <>,
 <>.
 
test_connect() ->
 {ok, Socket} = gen_tcp:connect("127.0.0.1", ?PORT, [binary, {active, true}, {packet, 0}]),
 Socket.
 
send_login(Uid, Uname) ->
 BinData = msg_user_base(Uid, Uname),
 msg(1001, BinData).


lua客户端 quick_client.lua:

-- quick_client.lua
require("socket")
require("pack")

PACKAGE_LENGTH  = 2
receiveStateLength = 0
receiveStateContent = 1


local host = "127.0.0.1"
local port = 8888
local client= assert(socket.connect(host, port))


local protocolCode = 1001
local luid = 2222
local lname = "xxx"
local llenname = string.len(lname)
local pstring = string.pack(">H>I>H>A", protocolCode, luid, llenname, lname)
local plen  = string.len(pstring)
local loginPacket = string.pack(">H>A", plen, pstring)

client:send(loginPacket)

function dispatchPacket(curPacket)
 packetId = curPacket:readPacketId()
 print("packetId is: ", packetId)
end


function createEmptyPacket()
 local packet = {packetLen   = 0, --包长度(int 类型)
     packetLenByteNum = 0, --包长度字节数
     packetLenBytes  = "", --包长度字节
     packetContentByteNum= 0, --包内容字节数
     packetContentBytes = "", --包内容字节
     packetId   = 0, --解析得到的包id
     pos     = 1, --包内容解到哪个位置了
 }
 
 local newpacket = {}
 
 function packet:readPacketId()
  if self.packetId == 0 then
   self.packetId = self:readUnint16()
  end
  return self.packetId
 end
 
 function packet:readByte()
  self.pos, rByte = string.unpack(self.packetContentBytes, ">b", self.pos)
  
  return rByte
 end
  
 function packet:readUnint16()
   self.pos, rUnint16 = string.unpack(self.packetContentBytes, ">H", self.pos)
   
   return rUnint16
  end
  
 function packet:readUnint32()
  self.pos, rUnint32 = string.unpack(self.packetContentBytes, ">I", self.pos)
  
  return rUnint32
 end
  
 function packet:readString()
  stringLen = self:rUnint16()
  rString  = string.sub(self.packetContentBytes, self.pos, self.pos + stringLen)
  self.pos = self.pos + stringLen
  return tostring(rString)
 end
 
 setmetatable(newpacket, {__index = packet})
 
 return newpacket
end


receiveState = receiveStateLength
local curPacket = nil

while true do
 if receiveState == receiveStateLength then
  if curPacket == nil then
   curPacket = createEmptyPacket()
  end
  
  local data
  local buffer, status, overflow = client:receive(PACKAGE_LENGTH - curPacket.packetLenByteNum)
  
  if buffer == nil then
   if status == "closed" then
    return
   end
   data = overflow
  else
   data = buffer
  end
  if data ~= nil then
   if string.len(data) ~= 0 then
    curPacket.packetLenBytes = string.pack("AA", curPacket.packetLenBytes, data)
   end
  end
  curPacket.packetLenByteNum = string.len(curPacket.packetLenBytes)
  
  if curPacket.packetLenByteNum == PACKAGE_LENGTH then
   nextPos, curPacket.packetLen = string.unpack(curPacket.packetLenBytes, ">H")
   
   receiveState = receiveStateContent
  end
 elseif receiveState == receiveStateContent then
  local data
  local buffer, status, overflow = client:receive(curPacket.packetLen - curPacket.packetContentByteNum)
  if buffer == nil then
   if status == "closed" then
    return
   end
   data = overflow
  else
   data = buffer
  end
  
  if data ~= nil then
   if string.len(data) ~= 0 then
    curPacket.packetContentBytes = string.pack("AA", curPacket.packetContentBytes, data)
   end
  end
  curPacket.packetContentByteNum = string.len(curPacket.packetContentBytes)
  if curPacket.packetContentByteNum == curPacket.packetLen then
   dispatchPacket(curPacket)
   curPacket = nil
   receiveState = receiveStateLength
  end
 end
end

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