主服务程序package com.chat.server;import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Vector;
/**
 * 服务器类, 无限循环等待客户端的连接, 并创建线程响应客户端
 * @author 刘优
 *
 */
public class ChatServer implements Runnable { private ServerSocket server; // serversocket
private int port; // 端口
private static Vector<Socket> clients; // 客户端socket集合
private static HashMap<String,PrintWriter> clientWriterMap; // 客户,字符流输出流MAP(可以根据用户名直接定位到writer)
private static HashMap<Socket,String> socketClientMap; // SOCKET,客户MAP
private static Vector<String []> blackUsers; // 用户黑名单对应关系 String[1] 是 String[0]的黑名单中的用户
private static HashMap<String,Boolean> clientTypeMap; // 客户,客户端类型MAP 客户端的类型有Window和telnet用户
private static Vector<ServerResponseThread> allThreads; // 所有的线程集合
private static HashMap<String,ServerResponseThread> threadMap;  // 用户名,线程Map
private boolean serverRunning; // 服务器运行标志
private boolean started; // 服务器启动标志 public ChatServer(int port) throws IOException {
this.port = port;
started = false; // 运行标志
} /**
 * 修改服务器端口号, 会导致服务重起
 * @param port
 */
public void setPort(int port) {
this.port = port;
if (started) {
stop();
}
try {
start(); // 启动服务器
} catch (IOException e) {
e.printStackTrace();
}
} /**
 * 初始化服务器
 *
 */
private void init() {
clients = new Vector<Socket>();
clientWriterMap = new HashMap<String,PrintWriter>();
socketClientMap = new HashMap<Socket,String>();
blackUsers = new Vector<String []>();
clientTypeMap = new HashMap<String,Boolean>();
serverRunning = true;
allThreads = new Vector<ServerResponseThread>();
threadMap = new HashMap<String,ServerResponseThread>();
} /**
 * 启动服务器线程
 * @throws IOException
 */
public void start() throws IOException {
init();
Thread serverThread = new Thread(this); // 新建一个线程来运行服务器
serverThread.start();
started = true;
}
/**
 * 重起服务器
 * @throws IOException
 */
public void restart() throws IOException {
if (started) {
stop(); // 如果已经启动, 则关闭后再重起
}
start();
} /**
 * 停止服务器, 清空所有集合
 *
 */
public void stop() {
serverRunning = false;
if (allThreads != null) {
for (int i = 0; i < allThreads.size(); ++i) {
allThreads.get(i).stopService();
}
allThreads.clear();
allThreads = null;
}
if (server != null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (clients != null) {
clients.clear();
clients = null;
}
if (clientWriterMap != null) {
clientWriterMap.clear();
clientWriterMap = null;
}
if (socketClientMap != null) {
socketClientMap.clear();
socketClientMap = null;
}
if (blackUsers != null) {
blackUsers.clear();
blackUsers = null;
}
if (clientTypeMap != null) {
clientTypeMap.clear();
clientTypeMap = null;
}
started = false;
} /**
 * 启动服务器RUN方法
 */
public void run() {
try {
server = new ServerSocket(port); // 创建SERVERSOCKET 服务器主对象
} catch (IOException e) {
e.printStackTrace();
}
while (serverRunning) {
    System.out.println("server is running at port : " + port);
    Socket socket;
try {
if (server == null) {
System.out.println("server is null");
break;
}
socket = server.accept(); // 监听客户端连接请求
clients.add(socket);
    System.out.println("client : " + socket.getInetAddress() + " attempt to enter the chat room"); // 打印客房信息...
    // 启动一个服务器端应答线程响应客户端. 并把服务器的各种集合共享,使之能访问其他线程
    ServerResponseThread response = new ServerResponseThread(socket,clientWriterMap,socketClientMap,blackUsers,clientTypeMap,threadMap);
    allThreads.add(response);
    response.setAllClientsThreadVector(allThreads);
    response.setClientSocketVector(clients);
    response.start(); // 启动响应线程
}
catch (SocketException ee) {
System.out.println("server is down"); // 关闭服务器的提示
}
catch (Exception e) {
e.printStackTrace();
}
}
} public void kickOff(String user) {
ServerResponseThread thread = threadMap.get(user);
//System.out.println("thread " + thread);
if (thread != null) {
thread.kickOff();
System.out.println("user " + user + " has been kicked...");
}
else {
System.out.println("user " + user + " not on line!");
}
}
}

解决方案 »

  1.   

    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【pauliuyou】截止到2008-07-08 20:28:13的历史汇总数据(不包括此帖):
    发帖的总数量:7                        发帖的总分数:60                       每贴平均分数:8                        
    回帖的总数量:28                       得分贴总数量:11                       回帖的得分率:39%                      
    结贴的总数量:3                        结贴的总分数:40                       
    无满意结贴数:1                        无满意结贴分:20                       
    未结的帖子数:4                        未结的总分数:20                       
    结贴的百分比:42.86 %               结分的百分比:66.67 %                  
    无满意结贴率:33.33 %               无满意结分率:50.00 %                  
    楼主该结一些帖子了
      

  2.   


    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();
      

  3.   


    /**
     * 注册新用户 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;
    }
    }
      

  4.   


    /**
     * 判断给定的用户是不是此客户端的黑名单中的用户
     * @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();
    }
    }
    }
      

  5.   


    /**
     * 用户发送文件请求处理, 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); }
    }
      

  6.   

    先看看,不过UserBean哪去了,不知道你的UserBean是怎么写的.....
      

  7.   


    package com.chat.util;import java.util.Calendar;
    import javax.swing.JLabel;
    /**
     * 时间类 , 获取时间信息
     * @author 刘优
     *
     */
    public class TimeBean {
    private static byte [] date; // year,month,day 年月日
    private static byte [] time; // hour,minute,second 时分秒
    private static JLabel label; /**
     * 获取当前时间
     */
    static {
    if (time == null || date == null) {
    date = new byte[4];
    time = new byte[3];
    }
    Calendar calendar = Calendar.getInstance();
    date[0] = (byte)(calendar.get(Calendar.YEAR) - 2000);
    date[1] = (byte)(calendar.get(Calendar.MONTH) + 1);
    date[2] = (byte)(calendar.get(Calendar.DAY_OF_MONTH));
    date[3] = (byte)(calendar.get(Calendar.DAY_OF_WEEK));
    time[0] = (byte)(calendar.get(Calendar.HOUR_OF_DAY));
    time[1] = (byte)(calendar.get(Calendar.MINUTE));
    time[2] = (byte)(calendar.get(Calendar.SECOND));
    new Thread(new Runnable() {
    /**
     * 使label成为电子时钟
     */
    public void run() {
    while (true) {
    if (label !=null) {
                 label.setText(getTime());
    }
             try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    nextSecond(); //走起来 获取下一秒
            }
    }
    }).start();
    } public static void setLabel(JLabel l) {
    label = l;
    }
    private static boolean leapYear(int year) {
    if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
    return true;
    }
    return false;
    }
    private static boolean overLastDay(int year,int month,int day) {
    int [] days = {32,30,32,31,32,31,32,32,31,32,31,32};
    if (month != 2 && day == days[month - 1]) {
    return true;
    }
    else if (leapYear(year) && day == 30) {
    return true;
    }
    else if (day == 29) {
    return true;
    }
    return false;
    }
    /**
     * 取得下一秒的时间
     *
     */
    public static void nextSecond() {
    if (++time[2] == 60) {  // 过了一分钟
    time[2] = 0;
    if (++time[1] == 60) {  // 过了一小时
    time[1] = 0;
    if (++time[0] == 24) {  // 过了一天
    time[0] = 0;
    if (overLastDay(date[0],date[1],++date[2])) {  // 过了一个月
    date[2] = 1;
    if (++date[1] == 13) {  // 过了一年
    date[1] = 1;
    date[0]++;
    }
    }
    }
    }
    }
    }
    /**
     * 格式化星期显示
     * @return
     */
    public static String getWeek() {
    String week = "星期";
    switch (date[3]) {
    case Calendar.SUNDAY :
    week += "日";
    break;
    case Calendar.MONDAY :
    week += "一";
    break;
    case Calendar.TUESDAY :
    week += "二";
    break;
    case Calendar.WEDNESDAY :
    week += "三";
    break;
    case Calendar.THURSDAY:
    week += "四";
    break;
    case Calendar.FRIDAY :
    week += "五";
    break;
    case Calendar.SATURDAY :
    week += "六";
    break;
    default:
    break;
    }
    return week;
    }
    /**
     * 取得格式化的日期
     */
    public static String getDate() {
    return (2000 + date[0]) + "-" + (date[1] < 10 ? "0" : "") + date[1] + "-" + (date[2] < 10 ? "0" : "") + date[2] + " " + getWeek();
    }
    /**
     * 获取当前时间的字符串, yyyy-mm-dd hh24:mi:ss
     * @return String
     */
    public static String getTime() {
    return (time[0] < 10 ? "0" : "") + time[0] + " : " + (time[1] < 10 ? "0" : "") + time[1] + " : " + (time[2] < 10 ? "0" : "") + time[2];
    }
    }
      

  8.   


    ackage com.chat.server;import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.HashSet;
    import java.util.Vector;/**
     * 处理用户信息的类 包括验证,写文件等操作
     *
     * @author 刘优
     *
     */
    public class UserBean { private static String userfile = "user/user"; // 用户文件,保存用户信息
    //private static String fileEncode = "UTF-8"; static {
    File folder = new File("user");
    if (!folder.exists()) {
    boolean b = folder.mkdir();
    }
    File f = new File(userfile);
    if (!f.exists()) {
        try {
    f.createNewFile();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    /**
     * 获取所有用户名 在usr目录下的urs文件中
     * @return vector
     */
        public static Vector<String> getUserNames() {
         File f = new File(userfile);
         Vector<String> v = new Vector<String>();
         if (!f.exists()) {
         try {
    f.createNewFile();
    } catch (IOException e) {
    e.printStackTrace();
    }
         return v;
         }
         BufferedReader fileReader = null;
         try {
    fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
    String one = fileReader.readLine();
    while (one != null) {
    v.add(one.split(":")[0]);
    one = fileReader.readLine();
    } } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if (fileReader != null)
    try {
    fileReader.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
         return v;
        }
        /**
         * 注册一个新用户
         * @param name
         * @param passwd
         */
        public static void register(String name,String passwd) {
         File f = new File(userfile);
         if (!f.exists()) {
         try {
    f.createNewFile();
    } catch (IOException e) {
    e.printStackTrace();
    }
         }
         FileWriter fileWriter = null;
         try {
    fileWriter = new FileWriter(userfile,true);
    MessageDigest key = MessageDigest.getInstance("MD5"); // 把用户的密码保存为MD5密文
    byte[] bytes = key.digest(passwd.getBytes());
    String s = "";
    for (byte b : bytes) {
    s += b;
    }
    fileWriter.write(name + ":" + s + ":5\n");
    fileWriter.flush();
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
    } finally {
    if (fileWriter != null)
    try {
    fileWriter.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }    }
        /**
         * 验证登录用户
         * @param name
         * @param passwd
         * @return boolean
         */
        public static int[] login(String name,String passwd) {
         //System.out.println("user passwd -- " + name + "," + passwd);
    name = name.trim();
    passwd = passwd.trim(); int[] rs = {1,1};     File f = new File(userfile);
         if (!f.exists()) {
         try {
    f.createNewFile();
    } catch (IOException e) {
    e.printStackTrace();
    }
         return rs;
         }     BufferedReader fileReader = null;
         try {
    fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
    MessageDigest key = MessageDigest.getInstance("MD5"); // 验证用户的密码
    byte[] bytes = key.digest(passwd.getBytes());
    String s = "";
    for (byte b : bytes) {
    s += b;
    }
    String one = fileReader.readLine();
    while (one != null) {
    //System.out.println("file : " + one);
    String [] infors = one.split(":");
    if (infors[0].equals(name)) {
    rs[0] = 0;
    rs[1] = 1;
    if (infors[1].trim().equals(s.trim())) {
    rs[1] = 0;
    }
    break;
    } one = fileReader.readLine();
    }
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
    }
    finally {
    if (fileReader != null)
    try {
    fileReader.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
         return rs;
        }
      

  9.   


    /**
         * 获取客户的黑名单
         * @param username
         * @return vector
         */
        public static Vector<String []> getBlackUsers(String username) {
         Vector<String []> v = new Vector<String []>();
         File f = new File("user/" + username + ".black");
         if (!f.exists()) {
         try {
    f.createNewFile();
    } catch (IOException e) {
    e.printStackTrace();
    }
         }
         BufferedReader fileReader = null;
         try {
    fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
    String one = fileReader.readLine();
    while (one != null) {
    String [] line = new String[] {username,one};
    v.add(line);
    one = fileReader.readLine();
    }
         } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if (fileReader != null)
    try {
    fileReader.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
         return v;
        }
        /**
         * 把其它用户放入黑名单
         * @param username
         * @param blackUser
         */
        public static void addBlack(String username,String blackUser) {
         File f = new File("user/" + username + ".black"); //黑名单文件
         if (!f.exists()) {
         try {
    f.createNewFile();
    } catch (IOException e) {
    e.printStackTrace();
    }
         }
         FileWriter writer = null;
         try {
    writer = new FileWriter(f,true); // 采用追加的方式写文件
    writer.write(blackUser + "\n");
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if (writer != null) {
    try {
    writer.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }    }
        /**
         * 写用户黑名单文件
         * @param username
         * @param blackUsers
         */
        public static void writeBlackFile(String username,Vector<String []> blackUsers) {
         PrintWriter theWriter = null;
         try {
    theWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream("user/" + username + ".black")));
    for (String[] pair : blackUsers) {
    if (pair[0].equals(username)) {
    theWriter.println(pair[1]);
    }
    }
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } finally {
    if (theWriter != null) {
    theWriter.close();
    }
    }    }
        /**
         * 获取用户的好友名单
         * @param name
         * @return hashset
         */
        public static HashSet<String> getFriends(String name) {
         HashSet<String> v = new HashSet<String>();
         File f = new File("user/" + name + ".friend");
         if (!f.exists()) {
         try {
    f.createNewFile();
    } catch (IOException e) {
    e.printStackTrace();
    }
         }
         BufferedReader fileReader = null;
         try {
    fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
    String one = fileReader.readLine();
    while (one != null) {
    v.add(one);
    one = fileReader.readLine();
    }
         } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if (fileReader != null)
    try {
    fileReader.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
         return v;
        }
        /**
         * 写用户好友文件 username.friend
         * @param username
         * @param friends
         */
        public static void writeFriendFile(String username,HashSet<String> friends) {
         PrintWriter theWriter = null;
         try {
    theWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream("user/" + username + ".friend")));
    for (String one : friends) {
    theWriter.println(one);
    }
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } finally {
    if (theWriter != null) {
    theWriter.close();
    }
    }
        }
        /**
         * 获取帮助文件内容 用来给TERM端客户显示
         * @return 文件内容
         */
        public static String getHelpFileContent() {
         String s = "";
         BufferedReader fileReader = null;
         try {
    fileReader = new BufferedReader(new InputStreamReader(new FileInputStream("user/help")));//获取帮助文件
    String one = fileReader.readLine();
    while (one != null) {
    s += one + "\n\r";
    one = fileReader.readLine();
    }
         } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if (fileReader != null)
    try {
    fileReader.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
         return s;
        }
        /**
         * 判断一个用户是否为已注册用户
         * @param name
         * @return
         */
        public static boolean isUser(String name) {
         BufferedReader fileReader = null;
         boolean is = false;
         try {
    fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(userfile)));
    String one = fileReader.readLine();
    while (one != null) {
    if (one.split(":")[0].equals(name)) {
    is = true;
    break;
    }
    one = fileReader.readLine();
    }
         } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if (fileReader != null)
    try {
    fileReader.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
         return is;
        }
    }
      

  10.   

    Main class
    package com.chat.main;import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;import com.chat.server.ChatServer;
    /**
     * 服务器主程序
     * @author 刘优
     *
     */
    public class ServerMain implements Runnable {
    private static int port = 8888;
    private BufferedReader keyReader;
    private ChatServer server; public ServerMain() throws IOException {
    keyReader = new BufferedReader(new InputStreamReader(System.in));
    server = new ChatServer(port);
    Thread listener = new Thread(this);
    listener.start();
    server.start();
    }
    /**
     * 接受控制台命令, 控制服务器
     */
    public void run() {
        while (true) {
         try {
         System.out.println("input command : ");
    String cmd = keyReader.readLine();
    if (cmd == null) break;
    if (cmd.equals("start")) {
    server.start();
    }
    else if (cmd.equals("restart")) {
    server.restart();
    }
    else if (cmd.startsWith("kick")) {
    server.kickOff(cmd.split(" ")[1]);
    }
    else if (cmd.equals("stop")) { // 停止服务器
    server.stop();
    }
    else if (cmd.equals("exit")) { // 退出程序
    server.stop();
    System.exit(0);
    }
    else if (!cmd.trim().equals("")) {
    System.out.println("command : " + cmd + " not recognized!");
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
        }
    }
    public static void main(String[] args) {
    if (args.length > 0)
    {
    try {
    port = Integer.parseInt(args[0]);
    }
    catch (Exception e) {}
    }
    try {
    ServerMain main = new ServerMain();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
      

  11.   


    package com.chat.util;import java.awt.Window;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;import javax.swing.JDialog;
    import javax.swing.JFrame;/**
     * 窗口显示设置类, 使窗口置中
     * @author 刘优
     *
     */
    public class WindowTool {

    /**
     * 居中显示窗口
     * @param w
     */
        public static void doView(Window w) {
        
    w.setSize(w.getToolkit().getScreenSize().width,w.getToolkit().getScreenSize().height - 40);
    w.setLocation(0,0);
    w.setVisible(true);
    if (w.getClass() == JFrame.class) {
        ((JFrame)w).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ((JFrame)w).setResizable(false);
    }
    if (w.getClass() == JDialog.class) {
    ((JDialog)w).setDefaultCloseOperation(JDialog.EXIT_ON_CLOSE);
    ((JDialog)w).setResizable(false);
    }
    }
        
        /**
         * 居中显示窗口
         * @param w
         * @param width
         * @param height
         */
    public static void doView(Window w,int width,int height) {
    w.setSize(width,height);
    int width2 = w.getToolkit().getScreenSize().width;
    width2 = (width2 - w.getWidth()) / 2;
    int height2 = w.getToolkit().getScreenSize().height;
    height2 = (height2 - w.getHeight()) / 2;
    w.setLocation(width2,height2);
    w.setVisible(true);
    if (w.getClass() == JFrame.class) {
        ((JFrame)w).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ((JFrame)w).setResizable(false);
    }
    /*
    if (w.getClass() == JDialog.class) {
    ((JDialog)w).setDefaultCloseOperation(JDialog.EXIT_ON_CLOSE);
    ((JDialog)w).setResizable(false);
    }
    */
    }
    /**
     * 设置窗口关闭
     * @param w 窗口
     */
    public static void doClose(Window w) {
    final Window w2 = w;
    w.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent we) {
        w2.dispose();
    }
    });
    }
    }
      

  12.   


    package com.chat.client;import java.awt.BorderLayout;
    import java.awt.Frame;
    import java.awt.GridLayout;
    import java.awt.HeadlessException;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.PrintWriter;import javax.swing.JButton;
    import javax.swing.JDialog;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JPasswordField;
    import javax.swing.JTextField;import com.chat.util.WindowTool;/**
     * 客户端登录窗口类, 用来验证登录和注册用户.
     * @author 刘优
     *
     */
    public class ClientLogin extends JDialog implements ActionListener,KeyListener { private static final long serialVersionUID = 1L;
    private JTextField username; // 用户名输入框
    private JPasswordField password; // 密码输入框
    private BufferedReader theReader; // 从服务器读数据的对象
    private PrintWriter theWriter; // 往服务器写数据的对象
    private ChatClient client; // 此窗口所属的CLIENT对象 /**
     * 初始化此窗口
     * @param owner
     * @param title
     * @param modal
     * @param theReader
     * @param theWriter
     * @throws HeadlessException
     */
    public ClientLogin(ChatClient owner, String title, boolean modal,BufferedReader theReader,PrintWriter theWriter) throws HeadlessException {
    super(owner, title, modal);
    this.client = owner;
    this.theReader = theReader;
    this.theWriter = theWriter;
    //初始化图形界面 setLayout(new BorderLayout());
    JPanel main = new JPanel(new GridLayout(2,2));
    JLabel title1 = new JLabel("登录信息 : ",JLabel.CENTER);
    JLabel l1 = new JLabel("        姓名 : ");
    JLabel l2 = new JLabel("        密码 : ");
    username = new JTextField();
    password = new JPasswordField();
    username.addKeyListener(this);
    password.addKeyListener(this);
    JButton ok = new JButton("登录");
    JButton register = new JButton("注册");
    JButton cancel = new JButton("取消"); ok.setActionCommand("login");
    register.setActionCommand("register");
    cancel.setActionCommand("cancel"); ok.addActionListener(this);
    register.addActionListener(this);
    cancel.addActionListener(this);
    main.add(l1);
    main.add(username);
    main.add(l2);
    main.add(password);
    JPanel buttonPane = new JPanel();
    buttonPane.add(ok);
    buttonPane.add(register);
    buttonPane.add(cancel);
    add(title1,"North");
    add(main);
    add(buttonPane,"South");
    WindowTool.doView(this,230,130); // 居中显示 } /**
     * 验证用户
     * @return String
     */
    public int verify() {
    return verify(username.getText(),new String(password.getPassword()));
    }
    /**
     * 把登录信息发送到服务器端, 格式为login=用户名=密码
     * @param username
     * @param password
     * @return
     */
    private int verify(String username,String password) {
    theWriter.println("login=" + username + "=" + password);
    theWriter.flush();
    String infor = null;
    try {
    infor = theReader.readLine();
    while (!infor.startsWith("login="))
    {
    infor = theReader.readLine();
    }
    //System.out.println(infor);
    } catch (IOException e) {
    e.printStackTrace();
    }
    int rs = -1;
    try {
    rs = Integer.parseInt(infor.substring(6));
    }
    catch (Exception e) {e.printStackTrace();}
    return rs; }
    public void actionPerformed(ActionEvent e) {
            String cmd = e.getActionCommand();
            if (cmd.equals("login")) {
             login();
            }
            else if (cmd.equals("cancel")) {
             System.exit(0);
            }
            else if (cmd.equals("register")) {
             register();
            }
    }
    /**
     * 注册新用户 格式为register=用户名=密码
     *
     */
    private void register() {
    if (username.getText().length() == 0 || password.getPassword().length == 0) {
    alarm("姓名和密码不能为空!");
         return;
         }
    theWriter.println("register=" + username.getText() + "=" + new String(password.getPassword()));
    theWriter.flush();
    String infor = null;
    try {
    infor = theReader.readLine();
    } catch (IOException e) {
    e.printStackTrace();
    }
    if (infor.startsWith("register=")) {
    if (infor.endsWith("1")) {
    alarm("注册新用户成功,请登录...");
    return;
    }
    }
    alarm("用户名已存在, 注册新用户失败,请重试...");
    }
    /**
     * 登录服务器
     *
     */
    private void login() {
    if (username.getText().length() == 0) {
    alarm("姓名不能为空!");
         return;
         }
         if (password.getPassword().length == 0) {
         alarm("密码不能为空!");
         return;
         }
    int verifyrs = verify();
         if (verifyrs == 0) {
         ((ChatClient)this.getOwner()).start(username.getText()); // 用户登录成功!启动ChatClient对象
         this.dispose(); // 把此窗口销毁
         }
         else {
         String infor = null;
         switch (verifyrs) {
         case -1 :
         infor = "未知错误";
         break;
         case 1 :
         infor = "缺少用户名";
         break;
         case 2 :
         infor = "缺少密码";
         break;
         case 3 :
         infor = "用户已经登录";
         break;
         case 4 :
         infor = "用户名错误";
         break;
         case 5 :
         infor = "密码错误";
         break;
         }
         alarm(infor);  // 如果失败, 提示失败详细信息
         }
    }
    private void alarm(String infor) {
    client.alarm(infor,true);
    }
    public void keyTyped(KeyEvent e) { }
    /**
     * 键盘监听响应
     */
    public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == 10) { // 响应回车, 输完用户名回车, 输入焦点转移到密码框上, 如果输完密码回车, 则直接登录
    if (e.getSource() == username) {
        password.requestFocus();
    }
    else {
    login();
    }
    } }
    public void keyReleased(KeyEvent e) {
    // 没啥用
    }}
      

  13.   


    package com.chat.client;import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Container;
    import java.awt.Font;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.FocusEvent;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    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.ServerSocket;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.util.HashSet;
    import java.util.Iterator;
    import javax.swing.JButton;
    import javax.swing.JComboBox;
    import javax.swing.JDialog;
    import javax.swing.JFileChooser;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JProgressBar;
    import javax.swing.JScrollBar;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;
    import com.chat.util.TimeBean;
    import com.chat.util.WindowTool;/**
     * 客户端JFRAME 主窗口
     * @author 刘优
     *
     */
    public class ChatClient extends JFrame implements Runnable,ActionListener,KeyListener {
    private static final long serialVersionUID = 1L;
    private static final String AUTHOR = "作者:刘优 版本:1.0";
    private ClientLogin login;
    private JTextArea main; // 显示消息的主窗口
    private JTextField input; // 用户输入栏
    private JComboBox usersCombo; // 其他所有用户控件
    private JScrollBar mainVerticalBar;
    private JLabel timer; // 时间显示标签
    private int width = 900; // 窗口宽度
    private int height = 600; // 窗口高度
    private JButton blackButton; // 黑名单按钮
    private JButton friendButton; // 好友按钮
    private JButton connectButton; // 连接按钮
    private JDialog dialog; // 消息子窗口
    private Container dialogPane;
    private JLabel alarmLabel2; // 消息标签
    private JLabel alarmLabel;
    private JLabel myNameLabel;
    private int dialogRs; // 消息窗口返回值
    private JPanel sPane;
    private JButton cl; // 消息窗口取消按钮
    private String welcome; private Socket socket; // 套接字
    private String ip;
    private int port;
    private InputStream inputStream;
    private OutputStream outputStream;
    private BufferedReader theReader; // 字符流输入对象
    private PrintWriter theWriter; // 字符流输出对象
    private boolean read; // 客户端运行标志
    private String myName; // 客户端用户名
    private HashSet<String> allusers; // 其他所有用户名
    private String toUser = "所有人"; // 发送悄悄话的用户名
    private String toUser2 = "所有人";
    private String sendFileName; // 要发送的文件名
    private int sendFilePort; // 发送文件用的端口
    private int bufferSize = 8193; // 发送文件时用的缓冲区大小
    private HashSet<String> myfriends; // 我的好友列表
    private boolean uiReady;
    private boolean connected; private static String encode = "UTF-8"; public ChatClient(String ip, int port) throws UnknownHostException, IOException {
        super("ChatRoom - ");
        this.ip = ip;
        this.port = port;
        createDialog();
        connect();
    } private void createDialog() {
            // 构建消息窗口, 但不显示, 如果有提示信息则显示.
    // 为了使之反应更快 dialog = new JDialog(this,"消息窗口",true);
    dialog.setSize(500,150);
    dialog.setLocation(this.getX() + 100, this.getY() + 100);
    dialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
    dialog.setResizable(false);
    dialogPane = dialog.getContentPane();
    alarmLabel = new JLabel("信息",JLabel.CENTER);
    dialog.setTitle("信息"); alarmLabel2 = new JLabel("",JLabel.CENTER);
    alarmLabel2.setFont(new Font("宋体",Font.BOLD,16));
    alarmLabel2.setForeground(Color.red);
    dialogPane.add(alarmLabel,"North");
    dialogPane.add(alarmLabel2); JButton b = new JButton("确定");
    b.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent ae) {
    dialog.setVisible(false);
    sPane.remove(cl);
    }
    });
    sPane = new JPanel();
    sPane.add(b);
    cl = new JButton("取消");
    cl.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent ae) {
    dialogRs = 1;
    dialog.setVisible(false);
    sPane.remove(cl);
    }
    });
    dialogPane.add(sPane,"South");
    }
    /**
     * 连接服务器, 需要提供IP和端口.
     * @throws UnknownHostException
     * @throws IOException
     */
    private void connect() throws UnknownHostException, IOException {
    try {
        socket = new Socket(ip,port); // 连接服务器
    }
    catch (Exception e) {
    alarm("服务器未准备就绪!",true); // 后面的TRUE表明提示信息很严重
    return;
    }
        inputStream = socket.getInputStream(); // 获取输入流
        outputStream = socket.getOutputStream(); // 获取写服务器的输出流
        theReader = new BufferedReader(new InputStreamReader(inputStream,encode)); //包装一下
        theWriter = new PrintWriter(new OutputStreamWriter(outputStream,encode),true); //包装一下
        welcome = theReader.readLine(); // 读取欢迎信息, 不显示, 没啥用TERM端会有用
        welcome = theReader.readLine();
        theWriter.println("client=window"); //告诉服务器, 客户端类型为window
    theWriter.flush();     // 启动验证登录窗口
        login = new ClientLogin(this,"登录",true,theReader,theWriter); } private void uiInit() {
    uiReady = true;
    main = new JTextArea();
    main.setEditable(false); // 不允许编辑主窗口
    input = new JTextField(30);
    input.setFont(new Font("宋体",Font.PLAIN,14));
    input.addKeyListener(this);
    JScrollPane scroll1 = new JScrollPane(main);
    mainVerticalBar = scroll1.getVerticalScrollBar();
    JPanel northPane = new JPanel();
    JLabel title = new JLabel("欢迎使用");
    JLabel timeInherit = new JLabel("系统当前时间 : ");
    timer = new JLabel();
    TimeBean.setLabel(timer);
    northPane.add(title);
    northPane.add(timeInherit);
    northPane.add(timer);
    northPane.add(new JLabel(" 日期 : " + TimeBean.getDate()));  // 获取当前时间并显示 JPanel southPane = new JPanel();
    usersCombo = new JComboBox(); // 所有用户列表 usersCombo.addActionListener(this);
    JButton send = new JButton("消息");
    JButton sendfile = new JButton("文件");
    friendButton = new JButton("好友");
    blackButton = new JButton("屏蔽");
    connectButton = new JButton("断开");
    sendfile.addActionListener(this);
    send.addActionListener(this);
    connectButton.addActionListener(this);
    friendButton.addActionListener(this);
    blackButton.addActionListener(this); myNameLabel = new JLabel();
    southPane.add(myNameLabel);
    southPane.add(usersCombo);
    southPane.add(input);
    southPane.add(send);
    southPane.add(sendfile);
    southPane.add(friendButton);
    southPane.add(blackButton);
    southPane.add(connectButton); this.add(northPane,"North");
    this.add(scroll1);
    this.add(southPane,"South");
    WindowTool.doView(this,width,height); this.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent we) {
    close(false,true);
        }
    });
    }
      

  14.   


    /**
     * 用户登录成功开始主方法
     * @param username
     */
    public void start(String username) {
    if (login != null) {
        login.dispose();
    }
    allusers = new HashSet<String>();
    myfriends = new HashSet<String>();
    myName = username;
    if (!uiReady) {
    uiInit();
    }
    setTitle("ChatRoom - " + username + "        " + AUTHOR); // 设置标题
    myNameLabel.setText("[" + username + "]对:"); // 显示我是谁
    connectButton.setText("断开"); // 设置按纽文本
    sendFilePort = 9999; // 文件发送和接收端口
    work(); // 开始工作啦
    } private void work() {
    Thread readThread = new Thread(this); // 新建一个线程来工作
    read = true;
    readThread.start();
    }
    /**
     * 显示警告信息
     * @param infor
     */
    public void alarm(String infor) {
    dialogRs = 0;
    alarm(infor,false);
    }
    public void alarm(String infor,boolean serious) {
    if (serious) {
        dialog.setTitle("错误!!");
        alarmLabel = new JLabel("发生错误 : ",JLabel.CENTER);
    }
    alarmLabel2.setText(infor);
    WindowTool.doView(dialog,350,110);
    }
    /**
     * 发送INPUT输入的文本
     *
     */
    private void send() {
    if (theWriter == null) {
    main.append("服务器的连接已断开!!\n"); alarm("服务器的连接已断开",true);
    return;
    } if (input.getText().length() > 0) {
    String infor = input.getText();
    if (!toUser.equals("所有人")) {
    infor = "to=" + toUser + "=" + infor; // 发送悄悄话
    }
    theWriter.println(infor);
    theWriter.flush();
    input.setText("");
    if (infor.equals("exit")) { // 如果是exit指令则退出系统
    close(false,true); }
    }
    else {
    main.append("您还没输入呢\n"); // 提示用户输入后再发送
    mainVerticalBar.setValue(mainVerticalBar.getMaximum()); // 设置主窗口,使之总是能显示最后一行 达到刷新效果
    }
    }
    /**
     * 处理按纽事件, 根据上面的文本来响应
     */
    public void actionPerformed(ActionEvent e) {
    String cmd = e.getActionCommand();
    if (cmd.equals("消息")) {
    send();
    }
    else if (cmd.equals("文件")) {
    sendFile();
    }
    else if (cmd.equals("屏蔽")) {
    toBlackList();
    }
    else if (cmd.equals("解禁")) {
    unBlackUser();
    }
    else if (cmd.equals("好友")) {
    toFriendList();
    }
    else if (cmd.equals("陌生")) {
    unFriendUser();
    }
    else if (cmd.equals("断开")) {
    disconnect();
    }
    else if (cmd.equals("连接")) {
    try {
    connect();
    } catch (UnknownHostException e1) {
    e1.printStackTrace();
    } catch (IOException e1) {
    e1.printStackTrace();
    }
    }
    else {
    // 处理按钮的文本
    Object obj = usersCombo.getSelectedItem();
    if (obj != null) {
    toUser = obj.toString();
    if (!toUser.equals("所有人")) {
    if (toUser.startsWith("好友-")) {
    toUser = toUser.substring(3);
    }
    toUser2 = toUser;
    if (theWriter == null) return;
        theWriter.println("isblack=" + toUser);
        theWriter.flush();
        for (String user : myfriends) {
         if (user.equals(toUser)) {
         friendButton.setText("陌生");
         break;
         }
        }
    }
    else {
    blackButton.setText("屏蔽");
    friendButton.setText("好友");
    }
    }
    }
    input.requestFocus();
    }
    /**
     * 把用户设为好友
     *
     */
    private void toFriendList() {
    if (theWriter == null) {
    disconnectAlarm();
    return;
    }
    if (toUser.equals("所有人")) {
    alarm("请选择目标用户");
    return;
    } theWriter.println("setfriend=" + toUser); // 告诉服务器, 我要把toUser加为发友
    theWriter.flush();
    }
    private void unFriendUser() {
    if (theWriter == null) {
    disconnectAlarm();
    return;
    }
    if (toUser.equals("所有人")) {
    alarm("请选择目标用户");
    return;
    }
    theWriter.println("unfriend=" + toUser); // 告诉服务器, 我要把toUser从好友中删除
    theWriter.flush();
    }
    private void disconnectAlarm() {
    main.append("服务器的连接已断开!!\n");
    alarm("服务器的连接已断开!!",true);
    }
    private void unBlackUser() {
    if (theWriter == null) {
    disconnectAlarm();
    return;
    }
    if (toUser.equals("所有人")) {
    alarm("请选择目标用户");
    return;
    }
    theWriter.println("unblack=" + toUser); // 告诉服务器, 要把toUser从黑名单中删除
    theWriter.flush();
    }
    private void toBlackList() {
    if (theWriter == null) {
    disconnectAlarm();
    return;
    }
    if (toUser.equals("所有人")) {
    alarm("请选择目标用户");
    return;
    }
    theWriter.println("black=" + toUser); // 告诉服务器, 要把toUser添加为黑名单
    theWriter.flush();
    }
      

  15.   


    /**
     * 给其他用户发送文件 格式为sendfile=filename=myname=tousername
     *
     */
    private void sendFile() {
    if (theWriter == null) {
    disconnectAlarm();
    return;
    }
    if (toUser.equals("所有人")) {
    alarm("请选择目标用户");
    return;
    }
    JFileChooser fileChooser = new JFileChooser();
    int returnVal = fileChooser.showOpenDialog(this);
        if(returnVal == JFileChooser.APPROVE_OPTION) {
         File f = fileChooser.getSelectedFile();
         if (!f.canRead()) {
         alarm("此文件不可读!"); // 文件不能读, 不能发
    return;
         }
                if (f.length() == 0) {
                 alarm("文件大小为零"); // 文件大小为0 发也没意思
    return;
    }
         sendFileName = f.getPath();
        }
        if (sendFileName == null) return;
    theWriter.println("sendfile=" + sendFileName.substring(sendFileName.lastIndexOf(File.separator) + 1) + "=" + myName + "=" + toUser);
    theWriter.flush();
    }
    /**
     * 主要的处理方法, 读取并处理服务器发送回来的指令
     */
    public void run() {
    while (read) {
    String infor = null;
    try {
    if (theReader != null) {
        infor = theReader.readLine();
        if (infor == null || theReader == null) {
         close(true,false);
        }
        if (infor.startsWith("myfriends=")) { // 获取我的好友名单
         myfriends.clear();
         String s = infor.substring(10).trim();
         String[] thenames = s.split(",");
         if (s.length() < 2) {
         continue;
         }
         for (int j = 0; j != thenames.length; ++j) {
         myfriends.add(thenames[j]);
         }
        }
        else if (infor.startsWith("allusers=")) { // 获取所有用户名
         allusers.clear();
         String str = infor.substring(9);
                String [] allUserArray = str.split(",");
                for (int i = 0; i != allUserArray.length; ++i) {
                 allusers.add(allUserArray[i]);
                }
        }
        else if (infor.startsWith("newlogin=")) { // 新用户登录了
         String newer = infor.substring(9);
         allusers.add(newer);
         handleUsers();
         infor = "系统\t[公共] : 用户 : " + newer + " 进入了聊天室";
        }
        else if (infor.startsWith("logout=")) { // 有用户推出聊天室
         String username = infor.substring(7);
         if (username.equals(myName)) {
         alarm("断开了服务器的连接!!!",true);
         main.append("断开了服务器的连接!!!\n");
         close(true,false);
         break;
         }
                allusers.remove(username.trim());
                handleUsers();
                infor = "系统\t[公共] : 用户 : " + username + " 离开了聊天室";
         }
        else if (infor.startsWith("sendfile=")) { // 有用户给我发送文件
         String [] infors = infor.split("=");
         String fromUser = infors[2];
         String toUser = infors[3];
         String filename = infors[1];
            sPane.add(cl);
            alarm("用户 : " + fromUser + " 想给您发送文件 \"" + filename + "\"  您是否原意接收?");
         if (dialogRs == 0) {
             Thread recFileThread = null;
                 try {
    recFileThread = new RecFileThread();
    recFileThread.start();
    } catch (Exception e) {
    dialogRs = 1;
    e.printStackTrace();
    }
            }
            theWriter.println("recfile=" + filename + "=" + fromUser + "=" + toUser + "=" + dialogRs);
            theWriter.flush();     }
        else if (infor.startsWith("recfile=")) { // 我给别人发送文件的响应
         String [] infors = infor.split("=");
         String toUser = infors[3];
         String rs = infors[4];
         String ip = infors[5].substring(1);
            if (rs.equals("0")) {
             alarm("用户 : " + toUser + " 同意接收您的文件...");
             Thread sendFile = new SendFileThread(ip);
             sendFile.start();
            }
            else {
             alarm("用户 : " + toUser + " 拒绝接收您的文件...");
            }
        }
        else if (infor.startsWith("black=")) { // 我被别人踢到黑名单了
         String other = infor.substring(6);
         alarm("用户 : " + other + " 把您放入了黑名单");
        }
        else if (infor.startsWith("blacksuccess=")) { // 我把某人踢到黑名单成功
         String other = infor.substring(13);
         alarm("把用户 : " + other + "添加到黑名单成功!");
         blackButton.setText("解禁");
        }
        else if (infor.startsWith("blacksuccess2=")) {
         String other = infor.substring(14);
         alarm("用户 : " + other + "已经在黑名单中了!");
        }
        else if (infor.startsWith("blackfile=")) {
         String other = infor.substring(10);
         alarm("用户 : " + other + " 把您放入了黑名单! 无法发送文件!");
        }
        else if (infor.startsWith("isblack=")) {
         String rs = infor.substring(8);
         if (rs.equals("1")) {
         blackButton.setText("解禁");
         }
         else {
         blackButton.setText("屏蔽");
         }
        }
        else if (infor.startsWith("unblack=")) { // 把用户从黑名单中删除
         String thename = infor.substring(8);
         alarm("用户 : " + thename + " 解禁成功!");
         blackButton.setText("屏蔽");
        }
        else if (infor.startsWith("beblacked=")) { // 我被别人加入了黑名单:(
         String thename = infor.substring(10);
         alarm("用户 : " + thename + " 把您放入了黑名单中!");
        }
        else if (infor.startsWith("unblacked=")) { // 别人把我从黑名单中删除了:)
         String thename = infor.substring(10);
         alarm("用户 : " + thename + " 把您从黑名单中清除!");
        }
        else if (infor.startsWith("setfriend=")) { // 别人把我加为好友了
         String thename = infor.substring(10);
         alarm("用户 : " + thename + " 已被您添加为好友!");
         myfriends.add(thename);
         handleUsers();
        }
        else if (infor.startsWith("setfriended=")) { // 我要把别人加为好友
         String thename = infor.substring(12);
         alarm("用户 : " + thename + " 把您添加为好友了!");
         handleUsers();
        }
        else if (infor.startsWith("unfriend=")) { // 我要把别人从好友中删除
         String thename = infor.substring(9);
         myfriends.remove(thename);
         alarm("用户 : " + thename + " 已经从好友中删除了!");
         handleUsers();
        }
        else if (infor.startsWith("unfriended=")) { // 别人把我从好友中删除了:(
         String thename = infor.substring(11);
         alarm("用户 : " + thename + " 把您从好友中删除了!");
         handleUsers();
        }
        if (infor.indexOf("=") != -1) { // 所有的服务器发送的指令都包含=号, 不显示之
         continue;
         }
    }
    else {
    alarm("服务器关闭,程序退出!",true);
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    main.append(infor + "\t\t[" + TimeBean.getTime() + "]\n"); // 显示新消息(别人的悄悄话, 或是公共消息)
    mainVerticalBar.setValue(mainVerticalBar.getMaximum()); // 自动调整主窗口的显示信息, 刷新位置
    } }
      

  16.   


    /**
     * 设置用户名控件,使之总是与服务器同步
     *
     */
    private void handleUsers() {
    usersCombo.removeAllItems();
    usersCombo.addItem("所有人");
    String toSelect = toUser2;
    Iterator<String> iter = allusers.iterator();
    while (iter.hasNext()) {
    String one = iter.next();
    Iterator iter2 = myfriends.iterator();
    while (iter2.hasNext()) {
    if (one.equals(iter2.next())) {
        usersCombo.addItem("好友-" + one);
        if (one.equals(toUser2)) {
         toSelect = "好友-" + one;
        }
        break;
    }
    }
    }
    iter = allusers.iterator();
    outfor :
    while (iter.hasNext()) {
    String one = iter.next();
    Iterator iter2 = myfriends.iterator();
    while (iter2.hasNext()) {
    if (one.equals(iter2.next())) {
        continue outfor;
    }
    }
    if (one.equals(myName)) continue;
    usersCombo.addItem(one);
    }
    usersCombo.setSelectedItem(toSelect);
    }
    public String getIp() {
    return ip;
    }
    public void setIp(String ip) {
    this.ip = ip;
    }
    public int getPort() {
    return port;
    }
    public void setPort(int port) {
    this.port = port;
    }
    public Socket getSocket() {
    return socket;
    }
    public void setSocket(Socket socket) {
    this.socket = socket;
    }
    /**
     * 断开连接
     *
     */
    private void disconnect() {
    close(false,false);
    }
    /**
     * 退出程序
     *
     */
    private void close(boolean fromService,boolean toExit) {
    if (!fromService) {
    if (theWriter != null) {
    theWriter.println("exit");
    theWriter.flush();
    }
    }
    read = false;
    if (theWriter != null) {
    theWriter.close();
    theWriter = null;
    }
    if (theReader != null) {
    try {
    theReader.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    theReader = null;
    }
    if (socket != null) {
    try {
    socket.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    socket = null;
    }
    connected = false;
    connectButton.setText("连接");
    if (toExit) {
        System.exit(0); // 退出程序
    }
    }
    public void keyTyped(KeyEvent e) { }
    public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == 10) { // 响应回车
    send();
    } }
    public void keyReleased(KeyEvent e) { }
    public void focusGained(FocusEvent e) { }
    public void focusLost(FocusEvent e) {
        input.requestFocus(); } /**
     * 发送文件线程....... 不会影响主程序的运行
     */
    class SendFileThread extends Thread {
    String toUserIp; // 对方IP
    FileInputStream fis = null; // 文件输入流
    boolean send = true; // 发送文件状态标志,如果为FALSE则取消发送
    JDialog dialog; // 进度显示窗口
    JProgressBar theBar; // 文件传输进度显示控件
    JPanel mainPane;
    JLabel percentLabel = new JLabel(); // 文件传输百分比标签
    JLabel bytesSendLabel = new JLabel(); // 传输字节标签
    JLabel totalBytesLabel = new JLabel(); // 文件大小标签
    JButton ok; // 确定按钮
    JButton cancel; // 取消按钮 public SendFileThread(String toUserIp) {
    super();
    this.toUserIp = toUserIp;
    try {
    fis = new FileInputStream(sendFileName);  // 文件输入流新建好了
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }
    dialog = new JDialog(ChatClient.this,"文件传输进度");  // 进度显示窗口就绪
    dialog.setLayout(new BorderLayout());
    mainPane = new JPanel();
    JPanel northPane = new JPanel(new GridLayout(1,3));
    northPane.add(percentLabel); // 百分比标签
    northPane.add(bytesSendLabel); // 已发送字节标签
    northPane.add(totalBytesLabel); // 文件总大小标签 dialog.add(northPane,"North"); // 设置窗口北边控件
    JPanel southPane = new JPanel();
    ok = new JButton("确定");
    ok.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent ae) {
    dialog.dispose();// 如果文件发送完毕,点击确定关闭此窗口
    }
    });
    southPane.add(ok);
    ok.setEnabled(false);
    cancel = new JButton("取消");
    cancel.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent ae) { // 在发送过程中, 随时可以取消文件发送
    send = false;
    alarm("您已经取消了文件发送任务!");
    }
    });
    southPane.add(cancel);
    dialog.add(southPane,"South");
    }
      

  17.   


    /**
     * 文件发送线程
     */
    public void run() {
    OutputStream out = null;
    Socket fileSocket = null;
    long fileLeng = -1;
    long theBytes = 0;
    try {
    // 建立SOCKET连接
    fileSocket = new Socket(toUserIp,sendFilePort); // 取得连接
    out = fileSocket.getOutputStream(); // 获取socket输出流对象,准备往这里写数据
    byte[] buffer = new byte[bufferSize]; // 创建一个缓冲区, 发送文件更快
    int bytesRead = 0; // 准备变量, 保存每次读取的字节数
    fileLeng = new File(sendFileName).length(); // 取得要发送的文件的字节数
    totalBytesLabel.setText("/" + fileLeng + ")字节"); // 设置总字节数标签
    byte[] lengByte = (fileLeng + "").getBytes(); // 把文件长度信息告诉文件接收方.....
    out.write(lengByte.length);
    out.write(lengByte);
    theBar = new JProgressBar(0,(int)(fileLeng/1024)); // 创建进度条.最大值为文件的总量/1024
    theBar.setValue(0);
    percentLabel.setText(("0%"));
    dialog.add(theBar);
    WindowTool.doView(dialog,350,100); // 居中显示此进度显示 // 开始发送文件
    while (send) {
    bytesRead = fis.read(buffer,0,buffer.length);  // 读取文件输入流
        if (bytesRead <= 0) { // 文件发送完毕,则退出循环
         break;
        }
        // 设置显示信息
        theBytes += bytesRead; // 累计当前已处理的字节数
        theBar.setValue((int)(theBytes / 1024)); // 处理进度条 使之正确显示
        bytesSendLabel.setText("(" + theBytes);
        percentLabel.setText((int)(((double)theBytes / fileLeng) * 100) + "%");// 显示百分比
        out.write(buffer,0,bytesRead); // 写入SOCKET输出流...........
    } } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (UnknownHostException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }
    finally {
    if (out != null) {
    try {
    out.close(); // 关闭输出流
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    if (fileSocket != null) {
    try {
    fileSocket.close(); // 关闭socket对象
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    if (fis != null) {
    try {
    fis.close(); // 关闭文件输入流对象
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    ok.setEnabled(true); // 可以点击确定按纽了
    cancel.setEnabled(false);
    if (theBytes == fileLeng) {
    alarm("文件" + sendFileName + "传输完毕!");
    }
    else if (send){
    alarm("文件接收方中断了接收 !");
    }
             sendFileName = null;
    }
    }
    /**
     * 文件接收线程类
     * 类似文件发送线程类
     * @author 刘优
     *
     */
        class RecFileThread extends Thread {
         FileOutputStream fos = null; // 文件输出流
         boolean recv = true;
    JDialog dialog; // 进度显示窗口
    JProgressBar theBar; // 进度条
    JPanel mainPane;
    JLabel percentLabel = new JLabel(); // 百分比标签
    JLabel bytesRecvLabel = new JLabel(); // 字节数标签
    JLabel totalBytesLabel = new JLabel(); // 总字节数标签
    JButton ok; // 确定按纽
    JButton cancel; // 取消按纽
    File fileToSave; // 要接收保存的文件对象     public RecFileThread() throws Exception {
         JFileChooser fileChooser = new JFileChooser();
    fileChooser.showSaveDialog(ChatClient.this);
    fileToSave = fileChooser.getSelectedFile(); // 取得要保存的文件对象 // 判断写权限
    if (!fileToSave.getParentFile().canWrite() && !fileToSave.canWrite()) {
    alarm("不能在目录 [" + fileToSave.getParent() + "] 中创建文件");
    throw new Exception("没有目录:[" + fileToSave.getParent() + "]的写权限");
    }
    try {
    fos = new FileOutputStream(fileToSave); // 取得文件输出流
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }
    dialog = new JDialog(ChatClient.this,"文件接收进度"); // 进度窗口
    dialog.setLayout(new BorderLayout());
    JPanel northPane = new JPanel(new GridLayout(1,3));
    northPane.add(percentLabel);
    northPane.add(bytesRecvLabel);
    northPane.add(totalBytesLabel); dialog.add(northPane,"North");
    JPanel southPane = new JPanel();
    ok = new JButton("确定");
    ok.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent ae) {
    dialog.dispose();
    }
    });
    southPane.add(ok);
    ok.setEnabled(false);
    cancel = new JButton("取消");
    cancel.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent ae) {
    recv = false;
    alarm("您已经取消了文件接收任务!");
    }
    });
    southPane.add(cancel);
    dialog.add(southPane,"South");
         }
         /**
          * 文件接收线程方法
          */
    public void run() {
    ServerSocket ss = null;
    Socket fileSocket = null;
    InputStream in = null;
    long fileLeng = 0;
    long theBytes = 0;
    try {
    // 创建服务器端
    ss = new ServerSocket(sendFilePort);
    // 等待发送方连接
    fileSocket = ss.accept(); in = fileSocket.getInputStream(); // 取得socket输入流
    byte[] buffer = new byte[bufferSize]; // 缓冲区
    int bytesRead = 0;
    int leng = in.read();
    in.read(buffer,0,leng);
    String s = new String(buffer,0,leng);
    fileLeng = Long.parseLong(s); // 先取得文件的总大小
    totalBytesLabel.setText("/" + s + ")字节");
    theBar = new JProgressBar(0,(int)(fileLeng/1024));
    theBar.setValue(0);
    percentLabel.setText(("0%"));
    dialog.add(theBar);
    WindowTool.doView(dialog,350,100); // 居中显示窗口
    // 开始接收文件
    while (recv) {
    bytesRead = in.read(buffer,0,buffer.length); // 读取SOCKET输入流
    if (bytesRead <= 0) {
    break;
    }
    // 设置显示信息
    theBytes += bytesRead;
        theBar.setValue((int)(theBytes / 1024)); // 设置显示的进度条
        bytesRecvLabel.setText(" ( " + theBytes);
        percentLabel.setText((int)(((double)theBytes / fileLeng) * 100) + "%");//设置百分比标签
    fos.write(buffer,0,bytesRead); // 写入文件输出流
    } } catch (IOException e) {
    e.printStackTrace();
    }
    finally {
    // 关闭资源
    if (in != null) {
    try {
    in.close(); //关闭socket输入流对象
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    if (fos != null) {
    try {
    fos.close(); // 关闭文件输出流对象
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    if (fileSocket != null) {
    try {
    fileSocket.close(); // 关闭socket对象
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    if (ss != null) {
    try {
    ss.close(); // 关闭文件接收服务
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    ok.setEnabled(true);
    cancel.setEnabled(false);
    if (theBytes == fileLeng) {
    alarm("文件接收完毕,文件保存为:" + fileToSave.getPath()+ " !");
        return;
    }
    else if (recv){
    alarm("文件接收被发送方中断 !");
    }
    fileToSave.delete();// 如果是非正常中断,则把已经接收的片断文件删除..........
    sendFileName = null;
    }
    }}
      

  18.   


    package com.chat.main;import java.io.IOException;
    import java.net.*;
    import java.security.KeyFactory;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.*;import com.chat.client.ChatClient;/**
     * 客户端启动主程序
     * @author 刘优
     *
     */
    public class ClientMain {
    public static void main(String[] args) {
    try {
    String ip = getMyIp();
    //System.out.println(ip);
    int port = 8888;
    if (args.length > 0)
    {
    ip = args[0]; if (args.length > 1)
    {
    try {
    port = Integer.parseInt(args[1]);
    }
    catch (Exception e) {
    System.out.println("port number : " + args[1] + " is not a integer!");
    }
    } }
    ChatClient client = new ChatClient(ip,port); // IP 和 端口
    } catch (Exception ee) {
    ee.printStackTrace();
    }
    }
    private static String getMyIp() throws Exception
    {
    Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces();
    InetAddress ip = null;
    while (allNetInterfaces.hasMoreElements())
    {
    NetworkInterface netInterface = (NetworkInterface)allNetInterfaces.nextElement();
    //System.out.println(netInterface.getName());
    Enumeration addresses = netInterface.getInetAddresses();
    while (addresses.hasMoreElements())
    {
    ip = (InetAddress)addresses.nextElement();
    if (ip != null && ip instanceof Inet4Address && !(ip.getHostAddress().startsWith("127.")))
    {
    //System.out.println("本机的IP = " + ip.getHostAddress());
    break;
    }
    }
    }
    return ip.getHostAddress(); }}
      

  19.   

    共有9个类.
    分别是
    ChatClient.java          
    ChatServer.java          
    ClientLogin.java         
    ClientMain.java          
    ServerMain.java          
    ServerResponseThread.java
    TimeBean.java            
    UserBean.java            
    WindowTool.java          java com.chat.server.Main portNumber
    起动服务器.java com.chat.client.ClientMain localhost portNumber
    起动客户端
      

  20.   


    楼主厉害啊!运行起来了,不错,感谢楼主。
    不过启动的命令应该是:
    java com.chat.main.ServerMain portNumber
    起动服务器.java com.chat.main.ClientMain localhost portNumber
    起动客户端,另外,请问是怎么验证用户的?还没来得及看代码。
      

  21.   

    用户密码是用MD5编码的. 在userbean里有方法处理.
      

  22.   

    DOS 下, telnet ip port 也可以登录聊天室
      

  23.   

    真能整啊这是自己背写的还是CTRL+C来的啊 好多啊
      

  24.   

    有一个缺憾就是DOS和窗口间不能发送文件,
      

  25.   

    我正在改造这个程序, 使之成为一台FTP服务器.