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>
* 服务器的实现效果: <br>
*<br>
* 1.输入-help得到所有有关服务器操作的命令 <br>
*<br>
* 2.输入-run进入服务器各项内容初始化 <br>
*<br>
* 3.输入-stop断开服务器 <br>
*<br>
* 4.输入-quit断开服务器,并退出操作 <br>
*<br>
* 5.服务器创建成功后,会通过单独的线程运行监听客户端信息(listenLink) <br>
*<br>
* 6.服务器接收到数据后,会将数据移交至数据分析器(analyseMes)处理 <br>
*<br>
* 7.当用户确定连接并确定昵称后,服务器将该用户的地址及姓名存储在infoMemory中。 <br>
*<br>
*<br>
*<br>
*<br>
* 服务器的类与方法: <br>
*<br>
* 1.测试服务器创建:testServer(String ip,int serverPort) <br>
*<br>
* 2.初始化服务器 :initServer(String ip,int serverPort) <br>
*<br>
* 3.确定IP与Port :fixServerLink(String ip,int serverPort) <br>
*<br>
* 4.信息监听器 :listenLink() <br>
*<br>
* 5.数据分析器 :analyseMes(String mes) <br>
*<br>
* 6.获取地址用户名:getConsumerName(SocketAddress sa) <br>
*<br>
* 7.数据转发器 :transforMes(String mes) <br>
*<br>
* 8.数据单项转发器:transforMesSingle(SocketAddress adr,String mes) <br>
*<br>
* 9.停止服务器 :cutServer() <br>
*<br>
* 10.获得帮助列表 :helpList() <br>
*<br>
* 11.错误提示方法 :errorTip(String str) <br>
*<br>
* 12.在主函数中进行相应操作 <br>
*<br>
*<br>
* 重点注意的地方: <br>
*<br>
* 与客户端相仿,为了顺利监听信息,需要另一个线程运行信息监听器
*
*/
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;
// 开始运行监听的变量
private boolean beStart = false;
// 信息存储器
private Hashtable<String, SocketAddress> userCache = new Hashtable<String, SocketAddress>();
/**
* 服务器初始化
*
* @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!");
// 可以开始运行变量
beStart = true;
}
catch (SocketException s)
{
// 如果出现异常,则服务器测试不通过
errorTip("!-The Server Initialization Fail!--new DatagramSocket(" + serverPort + ", " + serverAddr + ")");
return false;
}
return true;
}
/**
* 监听信息
*
*/
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());
// 将获取的数据传递至数据分析器
this.analyseMes(mes);
}
}
catch (IOException e)
{
errorTip("!-The Server Can not receive message");
}
}
/**
* 数据分析器,给予相应处理
*
* @param mes
*/
private void analyseMes(String mes)
{
// 获取当前客户端的地址:
SocketAddress adr = dp.getSocketAddress();
// -test:进行服务器与客户端的连接测试
// 若成功,则将该客户端发送成功消息
if (mes.trim().equalsIgnoreCase("-test"))
{
transforMesSingle(adr, "-test: !-From Server:Succeed in Testing.");
}
// -quit:接受客户端退出信息
// 将该用户的退出信息转发至所有在线成员
else if (mes.trim().equalsIgnoreCase("-quit"))
{
String name = this.getConsumerName(adr);
System.out.println(name + "//" + 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:接受客户端请求,将信息转发给相应客户
// 如果目标客户不存在,则向请求客户发送相应消息
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
// 如果存在则返回相应提示
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 + "//" + adr.toString() + " succeed in lanuching.");
}
}
// 一般消息将会转发至所有用户
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);
// 进行比较
if (sa.equals(adrs))
{
name = temp;
break;
}
}
return name;
}
/**
* 向所有的用户发送数据
*
* @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!");
}
}
/**
* 向单个用户发送数据
*
* @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" + " 获取服务器相应操作的帮助" + "\n" + "-run " + " 运行服务器,并同时建立信息监听" + "\n" + "-stop"
+ " 停止服务器" + "\n" + "-quit" + " 停止服务器,并退出命令" + "\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聊天室创建成功!");
Scanner input = new Scanner(System.in);
System.out.println("!-请输入服务端命令:");
// 开始输入
String command = null;
// 如果输入quit将断开连接,并退出操作
while (!(command = input.next()).equalsIgnoreCase("-quit"))
{
// 获取帮助
if (command.equalsIgnoreCase("-help"))
{
cs.helpList();
}
// 初始化服务器
if (command.equalsIgnoreCase("-run"))
{
boolean goon = true;
while (goon)
{
// 测试服务器创建,如果成功则同时为信息监听器建立线程
System.out.println("!-创建服务器并运行...");
if (cs.initServer(serverAddr, serverPort))
{
new Thread(cs).start();
goon = false;
}
else
System.out.println("!-服务器创建失败,请检查!");
}
}
// 关闭服务器
if (command.equalsIgnoreCase("-stop"))
{
cs.cutServer();
}
}
input.close();
cs.cutServer();
}
/**
* 错误提示
*
* @param str
*/
public static void errorTip(String str)
{
System.out.println("-----------------\n" + str + "\n-----------------");
}
}