package com.tianhe.frm.chat;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Scanner;
/**
*
*<br>
* 服務(wù)器的實(shí)現(xiàn)效果: <br>
*<br>
* 1.輸入-help得到所有有關(guān)服務(wù)器操作的命令 <br>
*<br>
* 2.輸入-run進(jìn)入服務(wù)器各項(xiàng)內(nèi)容初始化 <br>
*<br>
* 3.輸入-stop斷開服務(wù)器 <br>
*<br>
* 4.輸入-quit斷開服務(wù)器,并退出操作 <br>
*<br>
* 5.服務(wù)器創(chuàng)建成功后,會(huì)通過單獨(dú)的線程運(yùn)行監(jiān)聽客戶端信息(listenLink) <br>
*<br>
* 6.服務(wù)器接收到數(shù)據(jù)后,會(huì)將數(shù)據(jù)移交至數(shù)據(jù)分析器(analyseMes)處理 <br>
*<br>
* 7.當(dāng)用戶確定連接并確定昵稱后,服務(wù)器將該用戶的地址及姓名存儲(chǔ)在infoMemory中。 <br>
*<br>
*<br>
*<br>
*<br>
* 服務(wù)器的類與方法: <br>
*<br>
* 1.測試服務(wù)器創(chuàng)建:testServer(String ip,int serverPort) <br>
*<br>
* 2.初始化服務(wù)器 :initServer(String ip,int serverPort) <br>
*<br>
* 3.確定IP與Port :fixServerLink(String ip,int serverPort) <br>
*<br>
* 4.信息監(jiān)聽器 :listenLink() <br>
*<br>
* 5.數(shù)據(jù)分析器 :analyseMes(String mes) <br>
*<br>
* 6.獲取地址用戶名:getConsumerName(SocketAddress sa) <br>
*<br>
* 7.數(shù)據(jù)轉(zhuǎn)發(fā)器 :transforMes(String mes) <br>
*<br>
* 8.數(shù)據(jù)單項(xiàng)轉(zhuǎn)發(fā)器:transforMesSingle(SocketAddress adr,String mes) <br>
*<br>
* 9.停止服務(wù)器 :cutServer() <br>
*<br>
* 10.獲得幫助列表 :helpList() <br>
*<br>
* 11.錯(cuò)誤提示方法 :errorTip(String str) <br>
*<br>
* 12.在主函數(shù)中進(jìn)行相應(yīng)操作 <br>
*<br>
*<br>
* 重點(diǎn)注意的地方: <br>
*<br>
* 與客戶端相仿,為了順利監(jiān)聽信息,需要另一個(gè)線程運(yùn)行信息監(jiān)聽器
*
*/
public class ChatServer implements Runnable
{
private DatagramSocket ds = null;
private DatagramPacket dp = null;
private String serverIp = "localhost";
private int serverPort = 9999;
private InetAddress serverAddr = null;
// 開始運(yùn)行監(jiān)聽的變量
private boolean beStart = false;
// 信息存儲(chǔ)器
private Hashtable<String, SocketAddress> userCache = new Hashtable<String, SocketAddress>();
/**
* 服務(wù)器初始化
*
* @param ip
* @param serverPort
*/
public boolean initServer(InetAddress serverAddr, int serverPort)
{
this.serverAddr = serverAddr;
this.serverPort = serverPort;
try
{
ds = new DatagramSocket(serverPort, serverAddr);
System.out.println("!-The Server Initialization Success!");
// 可以開始運(yùn)行變量
beStart = true;
}
catch (SocketException s)
{
// 如果出現(xiàn)異常,則服務(wù)器測試不通過
errorTip("!-The Server Initialization Fail!--new DatagramSocket(" + serverPort + ", " + serverAddr + ")");
return false;
}
return true;
}
/**
* 監(jiān)聽信息
*
*/
public void listenLink()
{
byte[] buf = new byte[1024];
String mes = null;
try
{
dp = new DatagramPacket(buf, buf.length);
System.out.println("!-The Server starts listenning to message.");
while (beStart)
{
ds.receive(dp);
mes = new String(buf, 0, dp.getLength());
// 將獲取的數(shù)據(jù)傳遞至數(shù)據(jù)分析器
this.analyseMes(mes);
}
}
catch (IOException e)
{
errorTip("!-The Server Can not receive message");
}
}
/**
* 數(shù)據(jù)分析器,給予相應(yīng)處理
*
* @param mes
*/
private void analyseMes(String mes)
{
// 獲取當(dāng)前客戶端的地址:
SocketAddress adr = dp.getSocketAddress();
// -test:進(jìn)行服務(wù)器與客戶端的連接測試
// 若成功,則將該客戶端發(fā)送成功消息
if (mes.trim().equalsIgnoreCase("-test"))
{
transforMesSingle(adr, "-test: !-From Server:Succeed in Testing.");
}
// -quit:接受客戶端退出信息
// 將該用戶的退出信息轉(zhuǎn)發(fā)至所有在線成員
else if (mes.trim().equalsIgnoreCase("-quit"))
{
String name = this.getConsumerName(adr);
System.out.println(name + "http://" + adr + " quit! ");
transforMes("* " + name + "退出聊天室");
userCache.remove(name);
}
// -getList:接受客戶端獲取列表的請求
// 將所有用戶連接為字符串的形式,如:"-getList,用戶1,用戶2...用戶n"
else if (mes.trim().equals("-getList"))
{
StringBuffer list = new StringBuffer();
list.append("-getList,");
Enumeration<String> names = userCache.keys();
while (names.hasMoreElements())
{
list.append(names.nextElement() + ",");
}
transforMesSingle(dp.getSocketAddress(), list.toString());
}
// -to:接受客戶端請求,將信息轉(zhuǎn)發(fā)給相應(yīng)客戶
// 如果目標(biāo)客戶不存在,則向請求客戶發(fā)送相應(yīng)消息
else if (mes.indexOf("-to ") != -1 && mes.startsWith("-to "))
{
String main = mes.substring("-to ".length(), mes.length());
String toName = main.substring(0, main.indexOf(" "));
String name = this.getConsumerName(adr);
String con = name + " say to you :" + main.substring(toName.length() + 1, main.length());
if (!userCache.containsKey(toName))
transforMesSingle(adr, "!-The message can not be recevie by whom you send for,please check out.");
else
transforMesSingle(userCache.get(toName), con);
}
// -nick:接受客戶端登錄請求
// 如果輸入的匿名不存在,則登記該用戶與infoMemory
// 如果存在則返回相應(yīng)提示
else if (mes.indexOf("-nick ") != -1 && mes.startsWith("-nick "))
{
String nickName = mes.substring("-nick ".length(), mes.length());
if (userCache.containsKey(nickName))
transforMesSingle(adr, "-nick: !-The nickname you post is already exist,please try others.");
else
{
userCache.put(nickName, adr);
transforMes("Welcome " + nickName + " to Sunspot Chat!");
System.out.println(nickName + "http://" + adr.toString() + " succeed in lanuching.");
}
}
// 一般消息將會(huì)轉(zhuǎn)發(fā)至所有用戶
else
{
String name = this.getConsumerName(adr);
transforMes(name + ": " + mes);
}
}
/**
* 通過地址得到用戶的昵稱 由于Hashtable無法通過Value獲取Key,所有專門寫該方法
*
* @param sa
* @return
*/
private String getConsumerName(SocketAddress sa)
{
Enumeration<String> names = userCache.keys();
String name = null;
while (names.hasMoreElements())
{
String temp = names.nextElement();
SocketAddress adrs = userCache.get(temp);
// 進(jìn)行比較
if (sa.equals(adrs))
{
name = temp;
break;
}
}
return name;
}
/**
* 向所有的用戶發(fā)送數(shù)據(jù)
*
* @param mes
*/
public void transforMes(String mes)
{
byte[] buf = mes.getBytes();
DatagramPacket sendDatas = null;
Enumeration<SocketAddress> all = userCache.elements();
try
{
while (all.hasMoreElements())
{
sendDatas = new DatagramPacket(buf, buf.length, all.nextElement());
ds.send(sendDatas);
}
}
catch (SocketException s)
{
errorTip("!-The feedback address is error!");
}
catch (IOException i)
{
errorTip("!-Can not send message!");
}
}
/**
* 向單個(gè)用戶發(fā)送數(shù)據(jù)
*
* @param adr
* @param mes
*/
public void transforMesSingle(SocketAddress adr, String mes)
{
byte[] buf = mes.getBytes();
try
{
DatagramPacket sendDatas = new DatagramPacket(buf, buf.length, adr);
ds.send(sendDatas);
}
catch (SocketException s)
{
errorTip("!-The feedback address is error!");
}
catch (IOException i)
{
errorTip("!-Can not send message!");
}
}
/**
* 斷開連接
*
*/
public void cutServer()
{
beStart = false;
if (ds != null)
ds.close();
System.out.println("!-The ds is done.");
}
public void helpList()
{
System.out.println("-help" + " 獲取服務(wù)器相應(yīng)操作的幫助" + "\n" + "-run " + " 運(yùn)行服務(wù)器,并同時(shí)建立信息監(jiān)聽" + "\n" + "-stop"
+ " 停止服務(wù)器" + "\n" + "-quit" + " 停止服務(wù)器,并退出命令" + "\n");
}
/**
* 線程
*/
public void run()
{
listenLink();
}
/**
* 主要操作
*
* @param args
*/
public static void main(String[] args)
{
ChatServer cs = new ChatServer();
// serverAddr && serverPort
String serverIp = "localhost";
int serverPort = 9999;
InetAddress serverAddr = null;
if (args != null && args.length > 0)
{
int i = 0;
while (i < args.length)
{
// serverAddr
if (args[i].equalsIgnoreCase("-ServerAddr"))
{
i = i + 1;
serverIp = args[i];
continue;
}
// serverPort
int ti = 9999;
if (args[i].equalsIgnoreCase("-ServerPort"))
{
i = i + 1;
ti = Integer.parseInt(args[i]);
if (ti > 0)
{
serverPort = ti;
}
i = i + 1;
continue;
}
}
}
try
{
serverAddr = InetAddress.getByName(serverIp);
}
catch (UnknownHostException e)
{
e.printStackTrace();
System.exit(-1);
}
// 建立輸入
System.out.println("Lexiaofei聊天室創(chuàng)建成功!");
Scanner input = new Scanner(System.in);
System.out.println("!-請輸入服務(wù)端命令:");
// 開始輸入
String command = null;
// 如果輸入quit將斷開連接,并退出操作
while (!(command = input.next()).equalsIgnoreCase("-quit"))
{
// 獲取幫助
if (command.equalsIgnoreCase("-help"))
{
cs.helpList();
}
// 初始化服務(wù)器
if (command.equalsIgnoreCase("-run"))
{
boolean goon = true;
while (goon)
{
// 測試服務(wù)器創(chuàng)建,如果成功則同時(shí)為信息監(jiān)聽器建立線程
System.out.println("!-創(chuàng)建服務(wù)器并運(yùn)行...");
if (cs.initServer(serverAddr, serverPort))
{
new Thread(cs).start();
goon = false;
}
else
System.out.println("!-服務(wù)器創(chuàng)建失敗,請檢查!");
}
}
// 關(guān)閉服務(wù)器
if (command.equalsIgnoreCase("-stop"))
{
cs.cutServer();
}
}
input.close();
cs.cutServer();
}
/**
* 錯(cuò)誤提示
*
* @param str
*/
public static void errorTip(String str)
{
System.out.println("-----------------\n" + str + "\n-----------------");
}
}