主服务程序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!");
}
}
}
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!");
}
}
}
楼主【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 %
楼主该结一些帖子了
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); }
}
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];
}
}
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;
}
/**
* 获取客户的黑名单
* @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;
}
}
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();
}
}
}
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();
}
});
}
}
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) {
// 没啥用
}}
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);
}
});
}
/**
* 用户登录成功开始主方法
* @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();
}
/**
* 给其他用户发送文件 格式为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()); // 自动调整主窗口的显示信息, 刷新位置
} }
/**
* 设置用户名控件,使之总是与服务器同步
*
*/
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");
}
/**
* 文件发送线程
*/
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;
}
}}
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(); }}
分别是
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
起动客户端
楼主厉害啊!运行起来了,不错,感谢楼主。
不过启动的命令应该是:
java com.chat.main.ServerMain portNumber
起动服务器.java com.chat.main.ClientMain localhost portNumber
起动客户端,另外,请问是怎么验证用户的?还没来得及看代码。