源代碼下載鏈接:http://download.csdn.net/detail/sky453589103/9514686
自定義異常的目的是爲了更好的表示出錯的原因,能夠針對不同的異常執行不同的處理。
package SimpleChat;
public class ChatException extends Exception{
/**
*
*/
private static final long serialVersionUID = 1L;
public ChatException() {}
public ChatException(String desc) {
super(desc);
}
}
聊天程序的所有異常都應該繼承這個類。這個的實現是很簡單的,稍微懂點Java的都能看懂。舉一個請求消息的例子:
from:wapoonx
to:xwp
command:send
hello
以上就是一個發送消息的請求,from字段表明這個消息是從誰發送過來的。to這個字段表明要發送給誰,也就是接收方是誰。command這個字段表明要執行的命令。以一個空行爲標誌。隔開正文和頭部字段。在這個例子中正文是hello。服務器會根據command字段,從請求報文中選取自己想要的信息。
舉一個響應消息的例子:
code:0
description:success
(注意這裏是空的正文)
以上是一個響應消息的格式,code這個字段代表的是一個響應碼,這個響應碼代表着服務器執行響應的客戶請求的結果,0代表成功,其他代表出錯。description是響應消息的描述。不同的描述在客戶端可能有不同的處理。package SimpleChat;
import java.util.Map;
import java.util.TreeMap;
public class RequestMessage {
private String from = "";
private String to = "";
private String command = "";
private String rawContext = "";
public RequestMessage() {
}
public RequestMessage(String raw) {
parse(raw);
}
public String getFrom() {
return from;
}
public String getTo() {
return to;
}
public String getCommand() {
return command;
}
public String getContext() {
return rawContext;
}
public void setFrom(String f) {
from = f;
}
public void setTo(String to) {
this.to = to;
}
public void setCommand(String cmd) {
this.command = cmd;
}
public void setContext(String con) {
rawContext = con;
}
public String Format() {
String res = "from:" + from+ "\r\n";
res += "to:" + to + "\r\n";
res += "command:" + command + "\r\n\r\n";
res += rawContext;
return res;
}
private void parse(String raw) {
String[] temp = raw.split("\r\n\r\n");
String[] fields = temp[0].split("\r\n");
if (temp == null || fields == null) {
return ;
}
for (int i = 0; i < fields.length; ++i) {
if (fields[i].indexOf("from:") == 0) {
from = fields[i].substring("from:".length());
}
else if (fields[i].indexOf("to:") == 0) {
to = fields[i].substring("to:".length());
}
else if (fields[i].indexOf("command:") == 0) {
command = fields[i].substring("command:".length());
}
}
if (temp.length == 2) {
rawContext = temp[1];
}
}
public static Map<String, String> parseContext(String rawContext) throws ChatMessageException {
if (rawContext == null || rawContext.equals("")) {
return new TreeMap<String, String>();
}
Map<String, String> context = new TreeMap<String, String>();
String[] temp = rawContext.split("\r\n");
for (int i = 0; i < temp.length; ++i) {
String[] res = temp[i].split(":");
if (res.length == 2) {
context.put(res[0], res[1]);
} else {
throw new ChatMessageException("response message is invaild. context's format error");
}
}
return context;
}
public Map<String, String> parseContext() throws ChatMessageException {
return parseContext(this.rawContext);
}
}
上面這個類的理解難點在於parse函數。其實也很好懂。就是在上面舉得請求消息報文中的字段和正文分析出來。報文的頭部會有很多個字段,然後每個字段會被有一個對應的值,可能爲空。parse函數解析請求報文有下面幾個步驟: