霸哥的blog中提到过Erlang服务器在通信中与客户端的数据交换方式:yufeng
为了简单起见这个聊天室程序采用json,要使用到rfc4627 这个库
先定义一个Message类:
public class Message { String id; //消息ID String type; //消息类型 String from; //发送方 String to; //接收方 String subject; //主题 String content; //内容 Date creationDate; //时间 public Message(String type,String from,String to,String subject,String content){ this.id =MessageIdGenerator.nextId(); this.type=type; this.from=from; this.to=to; this.subject=subject; this.content=content; this.creationDate=new Date(); } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getFrom() { return from; } public void setFrom(String from) { this.from = from; } public String getTo() { return to; } public void setTo(String to) { this.to = to; } public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Date getCreationDate() { return creationDate; } public void setCreationDate(Date creationDate) { this.creationDate = creationDate; } } 再定义一个JSON的工具类:
public class JSONParaser { public static JSONObject getJSON(Object content){ try{ JSONObject result = JSONObject.fromObject(content); return result; } catch(Exception ex){ return null; } } public static Object getString(String json){ try{ JSONObject jobj=JSONObject.fromObject(json); return JSONObject.toBean(jobj); } catch(Exception ex){ return null; } } } 再修改SOCKET 发送部分代码:
public void sendMsg(Message msg){ try { String data=(JSONParaser.getJSON(msg)).toString(); oust.write(data.getBytes()); oust.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } 测试下发送后服务器端接收到的数据:
client_session dwmsg recived {message,undefined,msg, [6], undefined,undefined, <<"{\"content\":\"aaaaa\",\"creationDate\":{\"date\":27,\"day\":1,\"hours\":13,\"minutes\":10,\"month\":1,\"seconds\":26,\"time\":1330319426281,\"timezoneOffset\":-480,\"year\":112},\"from\":\"client1\",\"id\":\"x8yL-2\",\"subject\":\"chat\",\"to\":\"\",\"type\":\"msg\"}">>, undefined} client_session dwmsg sended
服务器端新建一个模块util_MessageParas,将收到的json数据转成内部可识的message:
%% Author: Administrator %% Created: 2012-2-27 %% Description: TODO: Add description to util_MessageParas -module(util_MessageParas). %% %% Include files %% %%-include("json.hrl"). -include("message.hrl"). %% %% Exported Functions %%<<"{\"content\":\"aaa\",\"creationDate\":{\"date\":27,\"day\":1,\"hours\":18,\"minutes\":8,\"month\":1,\"seconds\":26,\"time\":1330337306984,\"timezoneOffset\":-480,\"year\":112},\"from\":\"client1\",\"id\":\"289n-2\",\"subject\":\"chat\",\"to\":\"\",\"type\":\"msg\"}">> -export([paraseDecode/1]). %% %% API Functions %% %% %% Local Functions %% %paras json data to message paraseDecode(Bin)-> case rfc4627:decode(Bin) of {ok,Obj,_Re}-> paraElements(Obj); {error,Reason}-> {error,Reason} end . %we get elements from decoded json, %it has to be 7 elements paraElements(Obj)-> {obj,List}=Obj, Data =#message{}, %catch exception here try paraEle(List,Data) catch {error,Reason,NewData}-> io:format("Format"), {error,Reason,NewData} end . paraEle([Ele|Els],Data)-> NewData=para(Ele,Data), paraEle(Els,NewData) ; paraEle([],Data)-> Data . %length of content should not more than 1000 para({"content",Val},Data) when is_binary(Val)-> io:format("para content:~p~n",[Data]), Content=binary_to_list(Val), if length(Content)<1000 -> NewData=Data#message{content=Content}, io:format("paraed content:~p~n",[NewData]), NewData; true -> throw({error,"illegal Content value",Data}) end ; para({"to",Val},Data) when is_binary(Val)-> io:format("para to:~p~n",[Data]), To =binary_to_list(Val), NewData=Data#message{to=To} ; para({"id",Val},Data) when is_binary(Val)-> io:format("para id:~p~n",[Data]), Id=binary_to_list(Val), NewData=Data#message{id=Id} ; para({"subject",Val},Data) when is_binary(Val)-> io:format("para subject:~p~n",[Data]), Sub=binary_to_list(Val), %we should validate subject here if Sub=:="chat" -> NewData=Data#message{subject=Sub}; true -> %throw exception throw({error,"illegal subject value",Data}) end ; para({"type",Val},Data) when is_binary(Val)-> io:format("para type:~p~n",[Data]), Type = binary_to_list(Val), if Type=:="msg"-> NewData=Data#message{type=Type}; true -> %throw exception throw({error,"illegal type value",Data}) end ; para({"from",Val},Data) when is_binary(Val)-> io:format("para from:~p~n",[Data]), From=binary_to_list(Val), NewData=Data#message{from=From} ; para({"creationDate",Val},Data)-> Data ; para({Key,Val},Data)-> %no mache %throw exception throw({error,"unkown element",Data}) . paraseEncode()-> ok .
做下测试:
util_MessageParas:paraseDecode(<<"{\"content\":\"aaa\",\"creationDate\":{\"date\":27,\"day\":1,\"hours\":18,\"minutes\":8,\"month\":1,\"seconds\":26,\"time\":1330337306984,\"timezoneOffset\":-480,\"year\":112},\"from\":\"client1\",\"id\":\"289n-2\",\"subject\":\"chat\",\"to\":\"\",\"type\":\"msg\"}">>). para content:{message,undefined,undefined,undefined,undefined,undefined, undefined,undefined} paraed content:{message,undefined,undefined,undefined,undefined,undefined, "aaa",undefined} para from:{message,undefined,undefined,undefined,undefined,undefined,"aaa", undefined} para id:{message,undefined,undefined,"client1",undefined,undefined,"aaa", undefined} para subject:{message,"289n-2",undefined,"client1",undefined,undefined,"aaa", undefined} para to:{message,"289n-2",undefined,"client1",undefined,"chat","aaa", undefined} para type:{message,"289n-2",undefined,"client1",[],"chat","aaa",undefined} {message,"289n-2","msg","client1",[],"chat","aaa",undefined}
OK,收到的数据可以正常地解析为message了。
注:
在此处只需要将json数据的外层转换为message消息。message消息针对不同的类型和作用会有不同的json内容,所以内层数据应该在具体的消息处理部分再调用相应的paras处理。