package com.chat.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.PrintWriter;
import java.net.Socket;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
/** * 服务器端线程类 用来响应一个客户端连接和请求 * @author 刘优
*
*/
public class ServerResponseThread extends Thread {
private Vector<Socket> clients;
private Vector allThreads;
private Socket socket; // 与客户端连接的socket
private boolean iswork; // 线程运行结束标志
private boolean logined; // 用户登录标志
private boolean isTerm; // 客户端类型标志
private InputStream in; // 输入流
private OutputStream out; // 输出流
private BufferedReader theReader; // 字符输入对象,主要的对象,用来获得客户请求
private PrintWriter theWriter; // 字符输出对象,主要用来响应客户请求
private HashMap<Socket,String> socketClientMap; // socket,用户名的HASHMAP,有对应关系
private HashMap<String,PrintWriter> clientWriterMap; // 用户名和对应的字符输出流对象的hashMap
private HashMap<String,Boolean> clientTypeMap; // 用户名和对应的客户端类型hashmap
private HashMap<String,ServerResponseThread> threadMap; // 用户名和本对象的map
private Vector<String[]> blackUsers; // 客户的黑名单记录
private HashSet<String> friends; // 客户的好友记录
private String username; // 用户名
private String touser; // 发送方用户名
private String inheritString; // TERM端的用户提示串
private static String encode = "UTF-8";
private static String [] termCommands = {"ls","to","id","help","whoami","blackls","login","register","exit","sendfile","recfile","setfriend","unfriend","black","unblack","who"};
public ServerResponseThread(Socket socket,HashMap<String,PrintWriter> clientWriterMap,HashMap<Socket,String> map,Vector<String []> blackUsers,HashMap<String,Boolean> clientTypeMap,HashMap<String,ServerResponseThread> threadMap) throws IOException {
this.socket = socket;
if (socket == null) {
System.out.println("socket is null");
return;
}
socketClientMap = map;
iswork = true;
isTerm = true;
logined = false;
touser = "all";
in = socket.getInputStream();
out = socket.getOutputStream();
theReader = new BufferedReader(new InputStreamReader(in,encode));
theWriter = new PrintWriter(new OutputStreamWriter(out,encode),true);
this.clientWriterMap = clientWriterMap;
this.blackUsers = blackUsers;
this.clientTypeMap = clientTypeMap;
this.threadMap = threadMap;
// 在TERM端打印欢迎信息
welcome();
}
public void setClientSocketVector(Vector v) {
this.clients = v;
}
public void setAllClientsThreadVector(Vector v) {
this.allThreads = v;
}
/**
* 线程run方法,处理客户请求
*/
public void run() {
try {
work(); // 主要的应答方法..
close(false);
} catch (IOException e) {
e.printStackTrace();
System.out.println("client disconnect!!");
}
}
/**
* 核心方法 响应客户请求
* @throws IOException
*/
private void work() throws IOException {
String infor = null;
outer :
while (iswork) {
boolean doTerm = false;
infor = theReader.readLine();
if (infor == null) {
break;
}
if (infor.trim().equals("")) {
if (isTerm && logined) {
theWriter.print(inheritString + username + " $ "); // TERM端打印提示信息,如果用户不停地回车则打印此信息
theWriter.flush();
}
continue; // 不处理任何命令,因为没有命令
}
else if (infor.charAt(0) == '.' && isTerm) { // TERM端的命令处理
infor = infor.substring(1);
boolean legalCommand = false;
for (String command : termCommands) {
if (infor.startsWith(command)) {
legalCommand = true;
break;
}
}
if (!legalCommand) {
if (logined) {
theWriter.println(inheritString + username + " $ Command " + infor + " Not Legal!");
theWriter.print(inheritString + username + " $ ");
}
else {
theWriter.println("Command " + infor + " Not Legal!"); } theWriter.flush(); continue;
}
infor = doCmd(infor); // 把以'.'开头的命令中的'.'去掉,并把TERM端发来的命令格式化成为标准格式
doTerm = true;
}
if (infor.startsWith("client=")) { // 记录客户端类型 如果是TERM端则不会收到此信息
String client = infor.substring(7);
if (client.equals("window")) {
isTerm = false;
}
continue;
}
else if (infor.startsWith("login=")) { // 用户登录 格式: login=username=password
if (!login(infor)) {
continue;
}
}
else if (infor.equals("exit")) { // 客户端退出
iswork = false;
break;
}
else if (infor.startsWith("register=")) { // 注册新用户 register=username=password
if (!register(infor)) {
continue;
}
}
/////////////////////// // after login 用户登录请求!!
if (!logined) { // 用户未登录,不响应用户消息,需要重新登录
if (isTerm) {
welcome(); // 如果登录失败,在用户TERM端打印欢迎信息,提示重新登录
}
continue;
}
else if (infor.startsWith("to=")) { // 此客户端给其它用户发送悄悄话 to=touser=message
sendToUser(infor);
}
else if (infor.startsWith("sendfile=")) { // 此客户端给其他用户发送文件 sendfile=from=to=filename
if (!sendFile(infor)) {
continue;
}
}
else if (infor.startsWith("recfile=")) { // 客户端对于文件发送的响应
recFile(infor);
}
else if (infor.startsWith("black=")) { // 此客户端把其他某用户放入黑名单中 black=theuser
setBlack(infor);
}
else if (infor.startsWith("isblack=")) { // 判断某用户是否是黑名单中的用户
String thename = infor.substring(8).trim();
isBlack(thename);
}
else if (infor.startsWith("unblack=")) { // 此客户端把其他某用户从黑名单中删除 unblack=theuser
String thename = infor.substring(8);
unBlackUser(thename);
theWriter.println(infor);
theWriter.flush();
PrintWriter awriter = clientWriterMap.get(thename);
awriter.println("unblacked=" + username);
}
else if (infor.startsWith("setfriend=")) { // 此客户端把其他某用户放入好友中 setfriend=theuser
String thename = infor.substring(10);
setFridend(thename);
theWriter.println(infor);
theWriter.flush();
PrintWriter awriter = clientWriterMap.get(thename);
awriter.println("setfriended=" + username);
}
else if (infor.startsWith("unfriend=")) { // 此客户端把其他某用户从好友中删除 unfriend=theuser
String thename = infor.substring(9);
unFriend(thename);
theWriter.println(infor);
theWriter.flush();
PrintWriter awriter = clientWriterMap.get(thename);
awriter.println("unfriended=" + username);
}
else if (doTerm && infor.equals("help")) { // TERM端打印帮助信息
inherit();
}
else if (doTerm && infor.equals("ls")) { // TERM端显示在线用户
listUsers();
}
else if (doTerm && infor.equals("who")) { // 同上
listUsers();
}
else if (doTerm && infor.equals("whoami")) { // TERM端显示用户名
whoami();
}
else if (doTerm && infor.equals("id")) {
whoami();
}
else if (doTerm && infor.equals("blackls")) { // TERM端显示黑名单
listBlackUsers();
}
if (infor.indexOf("=") != -1 || doTerm) {
continue;
}
if (isTerm && !touser.equals("all")) {
sendToUser(touser,infor); // 发送悄悄话
theWriter.print(inheritString + username + " $ ");
}
else {
sendToAll(username,infor); // 发送群发消息
if (isTerm) {
theWriter.print(inheritString + username + " $ ");
}
}
}
} // end of work();
/**
* 注册新用户 register=username=password
*/
private boolean register(String infor) {
String userinfor = infor.substring(9);
String [] infors = userinfor.split("=");
String thename = infors[0];
String passwd = infors[1];
Vector<String> usernames = UserBean.getUserNames(); // UserBean是一个工具类, 提供静态方法, 可以从文件中读取用户信息
boolean exists = false;
for (int i = 0; i != usernames.size(); ++i) {
if (usernames.get(i).trim().equalsIgnoreCase(thename)) {
exists = true; // 要注册的用户已经是用户了, 请重新注册
break;
}
}
if (!exists) {
UserBean.register(thename,passwd);
if (isTerm) {
theWriter.println("Register Success!");
}
else {
theWriter.println("register=0");
}
}
else {
if (isTerm) {
theWriter.println("User already exists! Register failed try again....");
}
else {
theWriter.println("register=1");
}
}
theWriter.flush();
return true;
}
/**
* 登录用户 login=username=password
* @param infor
* @return
*/
private boolean login(String infor) {
String userinfor = infor.substring(6);
String [] infors = userinfor.split("=");
if (infors.length < 1) {
if (isTerm) {
theWriter.println("Username required!! Try again...");
}
else {
theWriter.println("login=1");
}
theWriter.flush();
return false;
}
if (infors.length < 2) {
if (isTerm) {
theWriter.println("Password required!! Try again...");
}
else {
theWriter.println("login=2");
}
theWriter.flush();
return false;
}
username = infors[0];
String passwd = infors[1];
Object obj = clientWriterMap.get(username.trim());
if (obj != null) {
if (isTerm) {
theWriter.println("User already logined!!");
}
else {
theWriter.println("login=3");
}
theWriter.flush();
return false;
}
int[] flag = UserBean.login(username,passwd);
if (flag[0] == 0 && flag[1] == 0) {
logined = true;
if (isTerm) {
theWriter.println("Login Success");
}
else {
theWriter.println("login=0");
}
}
else if (flag[0] == 1) {
if (isTerm) {
theWriter.println("Username is wrong. try again...");
}
else {
theWriter.println("login=4");
}
}
else if (flag[1] == 1)
{
if (isTerm) {
theWriter.println("Password is wrong. try again...");
}
else {
theWriter.println("login=5");
}
}
theWriter.flush();
if (logined) {
userInit();
}
return true;
}
/**
* 设置某用户为黑名单中的用户, 屏敝发言
* @param infor
*/
private void setBlack(String infor) {
String blackUser = infor.substring(6);
for (String[] pair : blackUsers) {
if (pair[1].equals(blackUser) && pair[0].equals(username)) {
theWriter.println("blacksuccess2=" + blackUser);
theWriter.flush();
return;
}
}
if (!UserBean.isUser(blackUser)) {
String infor2 = "不是合法用户";
if (isTerm) {
infor2 = " Not A legal user!";
}
theWriter.println(blackUser + infor2);
theWriter.flush();
return;
}
UserBean.addBlack(username,blackUser);
blackUsers.add(new String[] {username,blackUser}); // 加入黑名单对象中,第一个用户把第二个用户放入黑名单中
theWriter.println("blacksuccess=" + blackUser); // 提示此客户, 操作成功!
theWriter.flush();
if (!isOnline(blackUser)) { // 如果被加为黑名单的用户不在线则直接返回,否则给他打印提示信息
return;
}
PrintWriter awriter = clientWriterMap.get(blackUser);
awriter.println("beblacked=" + username);
}
/**
* 把用户加为好友, name是用户名
* @param name
*/
private void setFridend(String name) {
friends.add(name);
UserBean.writeFriendFile(username,friends); // 把此更改写入文件中永久保存
}
/**
* 把用户从好友中删除
* @param name
*/
private void unFriend(String name) { friends.remove(name); UserBean.writeFriendFile(username,friends); // 重写好友列表文件,使其永久保存
}
/**
* 把用户从黑名单中删除
* @param thename
*/
private void unBlackUser(String thename) {
for (String[] pair : blackUsers) {
if (pair[1].equals(thename) && pair[0].equals(username)) {
blackUsers.remove(pair); // 找着符合条件的对象
break;
}
}
UserBean.writeBlackFile(username,blackUsers); // 重写黑名单文件使其永久保存
}
/**
* 当此客户端要退出时, 清空黑名单中的所有记录,以释放资源
*
*/
private void removeFromBlackUsers() {
while (true) {
boolean delete = false;
for (String[] pair : blackUsers) {
if (pair[1].equals(username) || pair[0].equals(username)) {
blackUsers.remove(pair);
delete = true;
break;
}
}
if (!delete) break;
}
}
/**
* 判断给定的用户是不是此客户端的黑名单中的用户
* @param name
*/
private void isBlack(String name) {
int tt = 0;
for (String[] pair : blackUsers) {
if (pair[1].equals(name) && pair[0].equals(username)) {
tt = 1;
break;
}
}
theWriter.println("isblack=" + tt); // 如果是TT=1表示是,=0 表示不是
theWriter.flush();
}
/**
* 此方法主要用在TERM端,打印客户的黑名单
*
*/
private void listBlackUsers() {
String s = "\n\r";
for (String[] ss : blackUsers) {
if (ss[0].equals(username)) {
s += ss[1] + ",";
}
}
s += "\n\r";
s += "Total " + blackUsers.size() + " Users In Black List\n\r";
theWriter.println(s);
theWriter.print(inheritString + username + " $ ");
theWriter.flush();
}
/**
* 给其他用户发送悄悄话
* @param to
* @param infor
*/
private void sendToUser(String to,String infor) {
// 遍历黑名单, 查看用户to是不是将此客户端设为黑名单, 如果是则返回, 不发送信息,如果不是则发送消息
if (!UserBean.isUser(to) && isTerm) {
theWriter.println("User " + touser + " is not a legal user!");
theWriter.print(inheritString + username + " $ "); // TERM端的提示
theWriter.flush();
return;
}
for (String[] pair : blackUsers) {
if (pair[1].equals(username) && pair[0].equals(touser)) {
theWriter.println("black=" + touser);
return;
}
}
Object obj = clientWriterMap.get(to); // 获得要发送给消息的用户的Writer对象, 直接用此对象写信息即可让对方收到了
if (obj != null) {
PrintWriter writer = (PrintWriter)obj;
boolean isTargetTerm = clientTypeMap.get(to);
String kind = "私有";
String infor2 = username + "\t[" + kind + "] : " + infor;
if (isTargetTerm) {
kind = "Private";
}
if (username.equals(touser)) {
kind = "自己";
if (isTargetTerm) {
kind = "Myself";
} // 自言自语, 没什么大用处
}
String infor3 = username + "\t[" + kind + "] : " + infor; // 构建消息体
writer.println(infor3);
if (isTermByName(to)) {
writer.print(inheritString + to + " $ "); // TERM端打印提示
}
theWriter.println(infor2);
if (isTerm) {
theWriter.print(inheritString + username + " $ "); // TERM端的提示
}
writer.flush();
theWriter.flush();
}
else if (isTerm)
{
theWriter.println("User " + touser + " is not on line!");
theWriter.print(inheritString + username + " $ "); // TERM端的提示
theWriter.flush();
}
}
/**
* 发送悄悄话的另一个方法
* @param infor
*/
private void sendToUser(String infor) {
infor = infor.substring(3);
int equalpos = infor.indexOf("=");
if (equalpos != -1) {
touser = infor.substring(0,equalpos);
infor = infor.substring(equalpos + 1);
sendToUser(touser,infor);
}
else if (isTerm){
theWriter.println("Command not legal !\t type .help for more information....!");
theWriter.print(inheritString + username + " $ "); // TERM端的提示
theWriter.flush();
}
}
/**
* 发送所有人都能收到的信息
* @param infor
*/
private void sendToAll(String infor) {
Iterator<PrintWriter> iter = clientWriterMap.values().iterator();
while (iter.hasNext()) {
PrintWriter writer = iter.next();
writer.println(infor);
writer.flush();
}
}
/**
* 发送群发消息(黑名单问题要考虑)
* @param from
* @param infor
*/
private void sendToAll(String from,String infor) {
Set<String> names = clientWriterMap.keySet();
Iterator<String> iter = names.iterator();
while (iter.hasNext()) {
String thename = iter.next();
boolean isblack = false;
for (String[] pair : blackUsers) {
if (pair[1].equals(from) && pair[0].equals(thename)) {
isblack = true; // 发现黑名单, 把此客户端的发言屏敝了
break;
}
}
if (!isblack) {
PrintWriter awriter = clientWriterMap.get(thename);
if (isTermByName(thename)) {
awriter.println(from + "\t[Public] : " + infor); // 构建消息体
awriter.print(inheritString + thename + " $ "); // 发送消息
}
else {
awriter.println(from + "\t[公共] : " + infor); // 构建消息体
}
awriter.flush();
}
}
}
/**
* 用户发送文件请求处理, sendfile=文件名=From客户=To客户
* @param infor
* @return
*/
private boolean sendFile(String infor) {
String [] infors = infor.split("=");
String filename = infors[1];
String fromUser = infors[2];
String toUser = infors[3];
for (String[] pair : blackUsers) {
if (pair[1].equals(fromUser) && pair[0].equals(toUser)) {
theWriter.println("blackfile=" + toUser);
return false; // 如果被对方加入了黑名单, 则无法发送文件
}
}
Object obj = clientWriterMap.get(toUser);
if (obj != null) {
PrintWriter writer = (PrintWriter)obj;
writer.println("sendfile=" + filename + "=" + fromUser + "=" + toUser); // 提示要给发送文件的客户,有客户要给他发送文件
writer.flush();
}
return true;
}
/**
* 告诉另一个客户, 此客户同意接收文件.
* @param infor
*/
private void recFile(String infor) {
String [] infors = infor.split("=");
String filename = infors[1];
String fromUser = infors[2];
String toUser = infors[3];
Object obj = clientWriterMap.get(fromUser);
if (obj != null) {
PrintWriter writer = (PrintWriter)obj;
writer.println(infor + "=" + socket.getInetAddress());// 回应时告诉对方, 同意接收文件的一端的IP并建立了一个ServerSocket准备接收文件
writer.flush();
}
}
/**
* 打印此客户端的姓名
*
*/
private void whoami() {
theWriter.println(username);
theWriter.print(inheritString + username + " $ ");
theWriter.flush();
}
/**
* 探测某用户是不是TERM端
* @param name
* @return
*/
private boolean isTermByName(String name) {
Boolean obj = clientTypeMap.get(name);
return obj;
}
/**
* 用户初始化
*
*/
private void userInit() {
socketClientMap.put(socket,username);
clientWriterMap.put(username,theWriter);
blackUsers.addAll(UserBean.getBlackUsers(username));
inheritString = "Chat_";
clientTypeMap.put(username,false);
threadMap.put(username,this);
if (isTerm) {
clientTypeMap.put(username,true); // 记录客户端的类型
inherit();
}
else {
String allusers = "";
Collection<String> collection = socketClientMap.values();
Iterator<String> iter = collection.iterator();
while (iter.hasNext()) {
allusers += iter.next().trim() + ",";
}
if (allusers.length() > 0) {
allusers = allusers.substring(0,allusers.length() - 1);
}
theWriter.println("allusers=" + allusers); // 告诉客户端, 所有在线的客户有谁
theWriter.flush();
friends = UserBean.getFriends(username); // 告诉客户端他的好友名单
String myfriends = friends.toString();
theWriter.println("myfriends=" + myfriends.substring(1,myfriends.length() - 1));
theWriter.flush();
}
sendToAll("newlogin=" + username); // 告诉所有客户端 用户登录啦
}
/**
* TERM端打印欢迎信息
*
*/
private void welcome() {
String welcomeInfor = "\n\r\t\t\t\tWelcome To the Chat Room! \n\r\n\r\n\rPlease Input :\n\r\n\r.login username password to login \r\n.register username password to register a new User!\n\r.exit to cancel\n\n";
try {
welcomeInfor = new String(welcomeInfor.getBytes(encode));
}
catch (Exception e) {}
theWriter.println(welcomeInfor);
theWriter.flush();
}
/**
* TERM的提示信息
*
*/
private void inherit() {
String s = UserBean.getHelpFileContent();
theWriter.println(s);
theWriter.print(inheritString + username + " $ ");
theWriter.flush();
}
/**
* 在TERM端打印所有用户
*
*/
private void listUsers() {
String total = "\n\r" + clientWriterMap.keySet().toString() + "\n\r";
total += "Total " + clientWriterMap.size() + " User(s) On line!\n\r";
theWriter.println(total);
if (isTerm) {
theWriter.print(inheritString + username + " $ ");
}
theWriter.flush();
}
/**
* 把从TERM端发送的命令格式转化成标准格式
* @param cmd
* @return
*/
private String doCmd(String cmd) {
String s = "";
for (int i = 0; i != cmd.length(); ++i) {
char c = cmd.charAt(i);
if (c == ' ') {
c = '=';
}
s += c;
}
return s;
}
/**
* 判断用户名为name的用户是否在线
* @param name
* @return
*/
private boolean isOnline(String name) {
Iterator<String> iter = clientWriterMap.keySet().iterator();
while (iter.hasNext()) {
if (iter.next().equals(name)) {
return true;
}
}
return false;
}
public void kickOff() {
theWriter.println("\n\r{System} : You have been kicked out of the chat room.");
theWriter.flush();
stopService();
}
/**
* ChatServer调用此方法以断开此服务线程
*
*/
public void stopService() {
try {
close(true);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 退出线程 关闭各种资源
* @throws IOException
*/
private void close(boolean fromServer) throws IOException {
//System.out.println(allThreads);
iswork = false;
if (username != null) {
String leftinfor = "logout=" + username;
System.out.println(leftinfor);
sendToAll(leftinfor);
}
removeFromBlackUsers();
clientWriterMap.remove(username);
//ChatServer.remove(socket,this);
//if (!fromServer) {
allThreads.remove(this);
//}
clients.remove(socket);
socketClientMap.remove(socket);
threadMap.remove(username);
if (theReader != null) {
theReader.close();
}
if (theWriter != null) {
theWriter.close();
}
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
if (socket != null) {
socket.close();
}
//System.out.println(allThreads);
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.PrintWriter;
import java.net.Socket;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
/** * 服务器端线程类 用来响应一个客户端连接和请求 * @author 刘优
*
*/
public class ServerResponseThread extends Thread {
private Vector<Socket> clients;
private Vector allThreads;
private Socket socket; // 与客户端连接的socket
private boolean iswork; // 线程运行结束标志
private boolean logined; // 用户登录标志
private boolean isTerm; // 客户端类型标志
private InputStream in; // 输入流
private OutputStream out; // 输出流
private BufferedReader theReader; // 字符输入对象,主要的对象,用来获得客户请求
private PrintWriter theWriter; // 字符输出对象,主要用来响应客户请求
private HashMap<Socket,String> socketClientMap; // socket,用户名的HASHMAP,有对应关系
private HashMap<String,PrintWriter> clientWriterMap; // 用户名和对应的字符输出流对象的hashMap
private HashMap<String,Boolean> clientTypeMap; // 用户名和对应的客户端类型hashmap
private HashMap<String,ServerResponseThread> threadMap; // 用户名和本对象的map
private Vector<String[]> blackUsers; // 客户的黑名单记录
private HashSet<String> friends; // 客户的好友记录
private String username; // 用户名
private String touser; // 发送方用户名
private String inheritString; // TERM端的用户提示串
private static String encode = "UTF-8";
private static String [] termCommands = {"ls","to","id","help","whoami","blackls","login","register","exit","sendfile","recfile","setfriend","unfriend","black","unblack","who"};
public ServerResponseThread(Socket socket,HashMap<String,PrintWriter> clientWriterMap,HashMap<Socket,String> map,Vector<String []> blackUsers,HashMap<String,Boolean> clientTypeMap,HashMap<String,ServerResponseThread> threadMap) throws IOException {
this.socket = socket;
if (socket == null) {
System.out.println("socket is null");
return;
}
socketClientMap = map;
iswork = true;
isTerm = true;
logined = false;
touser = "all";
in = socket.getInputStream();
out = socket.getOutputStream();
theReader = new BufferedReader(new InputStreamReader(in,encode));
theWriter = new PrintWriter(new OutputStreamWriter(out,encode),true);
this.clientWriterMap = clientWriterMap;
this.blackUsers = blackUsers;
this.clientTypeMap = clientTypeMap;
this.threadMap = threadMap;
// 在TERM端打印欢迎信息
welcome();
}
public void setClientSocketVector(Vector v) {
this.clients = v;
}
public void setAllClientsThreadVector(Vector v) {
this.allThreads = v;
}
/**
* 线程run方法,处理客户请求
*/
public void run() {
try {
work(); // 主要的应答方法..
close(false);
} catch (IOException e) {
e.printStackTrace();
System.out.println("client disconnect!!");
}
}
/**
* 核心方法 响应客户请求
* @throws IOException
*/
private void work() throws IOException {
String infor = null;
outer :
while (iswork) {
boolean doTerm = false;
infor = theReader.readLine();
if (infor == null) {
break;
}
if (infor.trim().equals("")) {
if (isTerm && logined) {
theWriter.print(inheritString + username + " $ "); // TERM端打印提示信息,如果用户不停地回车则打印此信息
theWriter.flush();
}
continue; // 不处理任何命令,因为没有命令
}
else if (infor.charAt(0) == '.' && isTerm) { // TERM端的命令处理
infor = infor.substring(1);
boolean legalCommand = false;
for (String command : termCommands) {
if (infor.startsWith(command)) {
legalCommand = true;
break;
}
}
if (!legalCommand) {
if (logined) {
theWriter.println(inheritString + username + " $ Command " + infor + " Not Legal!");
theWriter.print(inheritString + username + " $ ");
}
else {
theWriter.println("Command " + infor + " Not Legal!"); } theWriter.flush(); continue;
}
infor = doCmd(infor); // 把以'.'开头的命令中的'.'去掉,并把TERM端发来的命令格式化成为标准格式
doTerm = true;
}
if (infor.startsWith("client=")) { // 记录客户端类型 如果是TERM端则不会收到此信息
String client = infor.substring(7);
if (client.equals("window")) {
isTerm = false;
}
continue;
}
else if (infor.startsWith("login=")) { // 用户登录 格式: login=username=password
if (!login(infor)) {
continue;
}
}
else if (infor.equals("exit")) { // 客户端退出
iswork = false;
break;
}
else if (infor.startsWith("register=")) { // 注册新用户 register=username=password
if (!register(infor)) {
continue;
}
}
/////////////////////// // after login 用户登录请求!!
if (!logined) { // 用户未登录,不响应用户消息,需要重新登录
if (isTerm) {
welcome(); // 如果登录失败,在用户TERM端打印欢迎信息,提示重新登录
}
continue;
}
else if (infor.startsWith("to=")) { // 此客户端给其它用户发送悄悄话 to=touser=message
sendToUser(infor);
}
else if (infor.startsWith("sendfile=")) { // 此客户端给其他用户发送文件 sendfile=from=to=filename
if (!sendFile(infor)) {
continue;
}
}
else if (infor.startsWith("recfile=")) { // 客户端对于文件发送的响应
recFile(infor);
}
else if (infor.startsWith("black=")) { // 此客户端把其他某用户放入黑名单中 black=theuser
setBlack(infor);
}
else if (infor.startsWith("isblack=")) { // 判断某用户是否是黑名单中的用户
String thename = infor.substring(8).trim();
isBlack(thename);
}
else if (infor.startsWith("unblack=")) { // 此客户端把其他某用户从黑名单中删除 unblack=theuser
String thename = infor.substring(8);
unBlackUser(thename);
theWriter.println(infor);
theWriter.flush();
PrintWriter awriter = clientWriterMap.get(thename);
awriter.println("unblacked=" + username);
}
else if (infor.startsWith("setfriend=")) { // 此客户端把其他某用户放入好友中 setfriend=theuser
String thename = infor.substring(10);
setFridend(thename);
theWriter.println(infor);
theWriter.flush();
PrintWriter awriter = clientWriterMap.get(thename);
awriter.println("setfriended=" + username);
}
else if (infor.startsWith("unfriend=")) { // 此客户端把其他某用户从好友中删除 unfriend=theuser
String thename = infor.substring(9);
unFriend(thename);
theWriter.println(infor);
theWriter.flush();
PrintWriter awriter = clientWriterMap.get(thename);
awriter.println("unfriended=" + username);
}
else if (doTerm && infor.equals("help")) { // TERM端打印帮助信息
inherit();
}
else if (doTerm && infor.equals("ls")) { // TERM端显示在线用户
listUsers();
}
else if (doTerm && infor.equals("who")) { // 同上
listUsers();
}
else if (doTerm && infor.equals("whoami")) { // TERM端显示用户名
whoami();
}
else if (doTerm && infor.equals("id")) {
whoami();
}
else if (doTerm && infor.equals("blackls")) { // TERM端显示黑名单
listBlackUsers();
}
if (infor.indexOf("=") != -1 || doTerm) {
continue;
}
if (isTerm && !touser.equals("all")) {
sendToUser(touser,infor); // 发送悄悄话
theWriter.print(inheritString + username + " $ ");
}
else {
sendToAll(username,infor); // 发送群发消息
if (isTerm) {
theWriter.print(inheritString + username + " $ ");
}
}
}
} // end of work();
/**
* 注册新用户 register=username=password
*/
private boolean register(String infor) {
String userinfor = infor.substring(9);
String [] infors = userinfor.split("=");
String thename = infors[0];
String passwd = infors[1];
Vector<String> usernames = UserBean.getUserNames(); // UserBean是一个工具类, 提供静态方法, 可以从文件中读取用户信息
boolean exists = false;
for (int i = 0; i != usernames.size(); ++i) {
if (usernames.get(i).trim().equalsIgnoreCase(thename)) {
exists = true; // 要注册的用户已经是用户了, 请重新注册
break;
}
}
if (!exists) {
UserBean.register(thename,passwd);
if (isTerm) {
theWriter.println("Register Success!");
}
else {
theWriter.println("register=0");
}
}
else {
if (isTerm) {
theWriter.println("User already exists! Register failed try again....");
}
else {
theWriter.println("register=1");
}
}
theWriter.flush();
return true;
}
/**
* 登录用户 login=username=password
* @param infor
* @return
*/
private boolean login(String infor) {
String userinfor = infor.substring(6);
String [] infors = userinfor.split("=");
if (infors.length < 1) {
if (isTerm) {
theWriter.println("Username required!! Try again...");
}
else {
theWriter.println("login=1");
}
theWriter.flush();
return false;
}
if (infors.length < 2) {
if (isTerm) {
theWriter.println("Password required!! Try again...");
}
else {
theWriter.println("login=2");
}
theWriter.flush();
return false;
}
username = infors[0];
String passwd = infors[1];
Object obj = clientWriterMap.get(username.trim());
if (obj != null) {
if (isTerm) {
theWriter.println("User already logined!!");
}
else {
theWriter.println("login=3");
}
theWriter.flush();
return false;
}
int[] flag = UserBean.login(username,passwd);
if (flag[0] == 0 && flag[1] == 0) {
logined = true;
if (isTerm) {
theWriter.println("Login Success");
}
else {
theWriter.println("login=0");
}
}
else if (flag[0] == 1) {
if (isTerm) {
theWriter.println("Username is wrong. try again...");
}
else {
theWriter.println("login=4");
}
}
else if (flag[1] == 1)
{
if (isTerm) {
theWriter.println("Password is wrong. try again...");
}
else {
theWriter.println("login=5");
}
}
theWriter.flush();
if (logined) {
userInit();
}
return true;
}
/**
* 设置某用户为黑名单中的用户, 屏敝发言
* @param infor
*/
private void setBlack(String infor) {
String blackUser = infor.substring(6);
for (String[] pair : blackUsers) {
if (pair[1].equals(blackUser) && pair[0].equals(username)) {
theWriter.println("blacksuccess2=" + blackUser);
theWriter.flush();
return;
}
}
if (!UserBean.isUser(blackUser)) {
String infor2 = "不是合法用户";
if (isTerm) {
infor2 = " Not A legal user!";
}
theWriter.println(blackUser + infor2);
theWriter.flush();
return;
}
UserBean.addBlack(username,blackUser);
blackUsers.add(new String[] {username,blackUser}); // 加入黑名单对象中,第一个用户把第二个用户放入黑名单中
theWriter.println("blacksuccess=" + blackUser); // 提示此客户, 操作成功!
theWriter.flush();
if (!isOnline(blackUser)) { // 如果被加为黑名单的用户不在线则直接返回,否则给他打印提示信息
return;
}
PrintWriter awriter = clientWriterMap.get(blackUser);
awriter.println("beblacked=" + username);
}
/**
* 把用户加为好友, name是用户名
* @param name
*/
private void setFridend(String name) {
friends.add(name);
UserBean.writeFriendFile(username,friends); // 把此更改写入文件中永久保存
}
/**
* 把用户从好友中删除
* @param name
*/
private void unFriend(String name) { friends.remove(name); UserBean.writeFriendFile(username,friends); // 重写好友列表文件,使其永久保存
}
/**
* 把用户从黑名单中删除
* @param thename
*/
private void unBlackUser(String thename) {
for (String[] pair : blackUsers) {
if (pair[1].equals(thename) && pair[0].equals(username)) {
blackUsers.remove(pair); // 找着符合条件的对象
break;
}
}
UserBean.writeBlackFile(username,blackUsers); // 重写黑名单文件使其永久保存
}
/**
* 当此客户端要退出时, 清空黑名单中的所有记录,以释放资源
*
*/
private void removeFromBlackUsers() {
while (true) {
boolean delete = false;
for (String[] pair : blackUsers) {
if (pair[1].equals(username) || pair[0].equals(username)) {
blackUsers.remove(pair);
delete = true;
break;
}
}
if (!delete) break;
}
}
/**
* 判断给定的用户是不是此客户端的黑名单中的用户
* @param name
*/
private void isBlack(String name) {
int tt = 0;
for (String[] pair : blackUsers) {
if (pair[1].equals(name) && pair[0].equals(username)) {
tt = 1;
break;
}
}
theWriter.println("isblack=" + tt); // 如果是TT=1表示是,=0 表示不是
theWriter.flush();
}
/**
* 此方法主要用在TERM端,打印客户的黑名单
*
*/
private void listBlackUsers() {
String s = "\n\r";
for (String[] ss : blackUsers) {
if (ss[0].equals(username)) {
s += ss[1] + ",";
}
}
s += "\n\r";
s += "Total " + blackUsers.size() + " Users In Black List\n\r";
theWriter.println(s);
theWriter.print(inheritString + username + " $ ");
theWriter.flush();
}
/**
* 给其他用户发送悄悄话
* @param to
* @param infor
*/
private void sendToUser(String to,String infor) {
// 遍历黑名单, 查看用户to是不是将此客户端设为黑名单, 如果是则返回, 不发送信息,如果不是则发送消息
if (!UserBean.isUser(to) && isTerm) {
theWriter.println("User " + touser + " is not a legal user!");
theWriter.print(inheritString + username + " $ "); // TERM端的提示
theWriter.flush();
return;
}
for (String[] pair : blackUsers) {
if (pair[1].equals(username) && pair[0].equals(touser)) {
theWriter.println("black=" + touser);
return;
}
}
Object obj = clientWriterMap.get(to); // 获得要发送给消息的用户的Writer对象, 直接用此对象写信息即可让对方收到了
if (obj != null) {
PrintWriter writer = (PrintWriter)obj;
boolean isTargetTerm = clientTypeMap.get(to);
String kind = "私有";
String infor2 = username + "\t[" + kind + "] : " + infor;
if (isTargetTerm) {
kind = "Private";
}
if (username.equals(touser)) {
kind = "自己";
if (isTargetTerm) {
kind = "Myself";
} // 自言自语, 没什么大用处
}
String infor3 = username + "\t[" + kind + "] : " + infor; // 构建消息体
writer.println(infor3);
if (isTermByName(to)) {
writer.print(inheritString + to + " $ "); // TERM端打印提示
}
theWriter.println(infor2);
if (isTerm) {
theWriter.print(inheritString + username + " $ "); // TERM端的提示
}
writer.flush();
theWriter.flush();
}
else if (isTerm)
{
theWriter.println("User " + touser + " is not on line!");
theWriter.print(inheritString + username + " $ "); // TERM端的提示
theWriter.flush();
}
}
/**
* 发送悄悄话的另一个方法
* @param infor
*/
private void sendToUser(String infor) {
infor = infor.substring(3);
int equalpos = infor.indexOf("=");
if (equalpos != -1) {
touser = infor.substring(0,equalpos);
infor = infor.substring(equalpos + 1);
sendToUser(touser,infor);
}
else if (isTerm){
theWriter.println("Command not legal !\t type .help for more information....!");
theWriter.print(inheritString + username + " $ "); // TERM端的提示
theWriter.flush();
}
}
/**
* 发送所有人都能收到的信息
* @param infor
*/
private void sendToAll(String infor) {
Iterator<PrintWriter> iter = clientWriterMap.values().iterator();
while (iter.hasNext()) {
PrintWriter writer = iter.next();
writer.println(infor);
writer.flush();
}
}
/**
* 发送群发消息(黑名单问题要考虑)
* @param from
* @param infor
*/
private void sendToAll(String from,String infor) {
Set<String> names = clientWriterMap.keySet();
Iterator<String> iter = names.iterator();
while (iter.hasNext()) {
String thename = iter.next();
boolean isblack = false;
for (String[] pair : blackUsers) {
if (pair[1].equals(from) && pair[0].equals(thename)) {
isblack = true; // 发现黑名单, 把此客户端的发言屏敝了
break;
}
}
if (!isblack) {
PrintWriter awriter = clientWriterMap.get(thename);
if (isTermByName(thename)) {
awriter.println(from + "\t[Public] : " + infor); // 构建消息体
awriter.print(inheritString + thename + " $ "); // 发送消息
}
else {
awriter.println(from + "\t[公共] : " + infor); // 构建消息体
}
awriter.flush();
}
}
}
/**
* 用户发送文件请求处理, sendfile=文件名=From客户=To客户
* @param infor
* @return
*/
private boolean sendFile(String infor) {
String [] infors = infor.split("=");
String filename = infors[1];
String fromUser = infors[2];
String toUser = infors[3];
for (String[] pair : blackUsers) {
if (pair[1].equals(fromUser) && pair[0].equals(toUser)) {
theWriter.println("blackfile=" + toUser);
return false; // 如果被对方加入了黑名单, 则无法发送文件
}
}
Object obj = clientWriterMap.get(toUser);
if (obj != null) {
PrintWriter writer = (PrintWriter)obj;
writer.println("sendfile=" + filename + "=" + fromUser + "=" + toUser); // 提示要给发送文件的客户,有客户要给他发送文件
writer.flush();
}
return true;
}
/**
* 告诉另一个客户, 此客户同意接收文件.
* @param infor
*/
private void recFile(String infor) {
String [] infors = infor.split("=");
String filename = infors[1];
String fromUser = infors[2];
String toUser = infors[3];
Object obj = clientWriterMap.get(fromUser);
if (obj != null) {
PrintWriter writer = (PrintWriter)obj;
writer.println(infor + "=" + socket.getInetAddress());// 回应时告诉对方, 同意接收文件的一端的IP并建立了一个ServerSocket准备接收文件
writer.flush();
}
}
/**
* 打印此客户端的姓名
*
*/
private void whoami() {
theWriter.println(username);
theWriter.print(inheritString + username + " $ ");
theWriter.flush();
}
/**
* 探测某用户是不是TERM端
* @param name
* @return
*/
private boolean isTermByName(String name) {
Boolean obj = clientTypeMap.get(name);
return obj;
}
/**
* 用户初始化
*
*/
private void userInit() {
socketClientMap.put(socket,username);
clientWriterMap.put(username,theWriter);
blackUsers.addAll(UserBean.getBlackUsers(username));
inheritString = "Chat_";
clientTypeMap.put(username,false);
threadMap.put(username,this);
if (isTerm) {
clientTypeMap.put(username,true); // 记录客户端的类型
inherit();
}
else {
String allusers = "";
Collection<String> collection = socketClientMap.values();
Iterator<String> iter = collection.iterator();
while (iter.hasNext()) {
allusers += iter.next().trim() + ",";
}
if (allusers.length() > 0) {
allusers = allusers.substring(0,allusers.length() - 1);
}
theWriter.println("allusers=" + allusers); // 告诉客户端, 所有在线的客户有谁
theWriter.flush();
friends = UserBean.getFriends(username); // 告诉客户端他的好友名单
String myfriends = friends.toString();
theWriter.println("myfriends=" + myfriends.substring(1,myfriends.length() - 1));
theWriter.flush();
}
sendToAll("newlogin=" + username); // 告诉所有客户端 用户登录啦
}
/**
* TERM端打印欢迎信息
*
*/
private void welcome() {
String welcomeInfor = "\n\r\t\t\t\tWelcome To the Chat Room! \n\r\n\r\n\rPlease Input :\n\r\n\r.login username password to login \r\n.register username password to register a new User!\n\r.exit to cancel\n\n";
try {
welcomeInfor = new String(welcomeInfor.getBytes(encode));
}
catch (Exception e) {}
theWriter.println(welcomeInfor);
theWriter.flush();
}
/**
* TERM的提示信息
*
*/
private void inherit() {
String s = UserBean.getHelpFileContent();
theWriter.println(s);
theWriter.print(inheritString + username + " $ ");
theWriter.flush();
}
/**
* 在TERM端打印所有用户
*
*/
private void listUsers() {
String total = "\n\r" + clientWriterMap.keySet().toString() + "\n\r";
total += "Total " + clientWriterMap.size() + " User(s) On line!\n\r";
theWriter.println(total);
if (isTerm) {
theWriter.print(inheritString + username + " $ ");
}
theWriter.flush();
}
/**
* 把从TERM端发送的命令格式转化成标准格式
* @param cmd
* @return
*/
private String doCmd(String cmd) {
String s = "";
for (int i = 0; i != cmd.length(); ++i) {
char c = cmd.charAt(i);
if (c == ' ') {
c = '=';
}
s += c;
}
return s;
}
/**
* 判断用户名为name的用户是否在线
* @param name
* @return
*/
private boolean isOnline(String name) {
Iterator<String> iter = clientWriterMap.keySet().iterator();
while (iter.hasNext()) {
if (iter.next().equals(name)) {
return true;
}
}
return false;
}
public void kickOff() {
theWriter.println("\n\r{System} : You have been kicked out of the chat room.");
theWriter.flush();
stopService();
}
/**
* ChatServer调用此方法以断开此服务线程
*
*/
public void stopService() {
try {
close(true);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 退出线程 关闭各种资源
* @throws IOException
*/
private void close(boolean fromServer) throws IOException {
//System.out.println(allThreads);
iswork = false;
if (username != null) {
String leftinfor = "logout=" + username;
System.out.println(leftinfor);
sendToAll(leftinfor);
}
removeFromBlackUsers();
clientWriterMap.remove(username);
//ChatServer.remove(socket,this);
//if (!fromServer) {
allThreads.remove(this);
//}
clients.remove(socket);
socketClientMap.remove(socket);
threadMap.remove(username);
if (theReader != null) {
theReader.close();
}
if (theWriter != null) {
theWriter.close();
}
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
if (socket != null) {
socket.close();
}
//System.out.println(allThreads);
}
}