?? server.java
字號:
/**
* QQ聊天室服務器端
*/
import java.net.*;
import java.io.*;
import java.util.*;
public class Server implements Protocol {
/*
* 用戶名存入key,線程存入對應value
*/
private static Map users = new HashMap();
/**
* 用戶線程類,每個用戶一個線程
*/
static class UserThread extends Thread {
private Socket s;
private String username = "";
private PrintWriter out;
private static int online;// 統計在線人數
private static String lock = "";
public UserThread(Socket s) {
this.s = s;
}
public void run() {
try {
/*
* 創建流
*/
InputStream is = s.getInputStream();
InputStreamReader ir = new InputStreamReader(is, "GBK");
// java.nio.charset.Charset.defaultCharset());
BufferedReader in = new BufferedReader(ir);
OutputStream os = s.getOutputStream();
OutputStreamWriter or = new OutputStreamWriter(os, "GBK");
out = new PrintWriter(or);
out.println(VERSION);
out.flush();
/*
* 判斷版本是否過期
*/
if (!in.readLine().equals(VERSION)) {
throw new Exception("版本過期");
}
this.username = in.readLine();
synchronized (lock) {
/*
* 讀取用戶名,并判斷是否已經存在
*/
if (isExist(this.username)) {
throw new ExistException();
}
/*
* 登陸成功
*/
out.println(SYSTEM_MSG);
out.flush();
/*
* 通知所有人有新用戶登陸
*/
sendAll(SYSTEM_MSG + ADD_USER + this.username);
/*
* 刷新在線人數
*/
System.out.print("\rOnline:" + ++online);
/*
* 給本線程用戶發送在線用戶列表
*/
listAll();
/*
* 將本用戶加入集合
*/
users.put(this.username, this);
}
String msg = "";
String touser = "All";
while (!s.isClosed()) {
while (!s.isClosed() && (msg = in.readLine()) != null
&& msg.length() > 0) {
/*
* 收到用戶退出的系統信息,刪除集合中對應項,通知所有用戶
*/
if (msg.startsWith(SYSTEM_MSG + USER_LOGOUT)) {
synchronized (lock) {
users.remove(this.username);
}
sendAll(SYSTEM_MSG + DELETE_USER + this.username);
s.close();
System.out.print("\rOnline:" + --online + " ");
}
/*
* 收到聊天信息,解析出發送對象和信息內容,并發送
*/
else {
touser = msg.substring(0, msg.indexOf(NAME_END));
msg = msg.replaceFirst(touser + NAME_END, "");
send(msg, touser);
}
}
}
}
/*
* 登陸時出現用戶名已存在情況,通知用戶
*/
catch (ExistException e) {
out.println(SYSTEM_MSG + USER_EXIST);
out.flush();
} catch (Exception e) {
} finally {
try {
s.close();
} catch (Exception e) {
}
}
}
/**
* 發送信息給所有用戶
*/
private void sendAll(String msg) {
Set s = users.keySet();
Iterator it = s.iterator();
while (it.hasNext()) {
UserThread t = (UserThread) users.get(it.next());
if (t != this)
t.sendUser(msg);
}
}
/**
* 給本線程發送在線用戶列表
*/
private void listAll() {
Set s = users.keySet();
Iterator it = s.iterator();
while (it.hasNext()) {
this.sendUser(SYSTEM_MSG + EXIST_USERS + it.next());
}
}
/**
* 判斷用戶名是否已經有人使用
*/
private boolean isExist(String name) {
Set s = users.keySet();
Iterator it = s.iterator();
while (it.hasNext()) {
if (name.equals((String) it.next())) {
return true;
}
}
return false;
}
/**
* 給本線程對應的用戶發信息
*/
private void sendUser(String msg) {
out.println(msg);
out.flush();
// System.out.println("to " + this.username + ": " + msg);// 調試用代碼
}
/**
* 給指定對象發送信息
*/
private void send(String msg, String touser) {
/*
* 調用相應函數,給所有人發信息時
*/
if (touser.equals("All")) {
sendAll(this.username + NAME_END + msg);
return;
}
/*
* 根據發送目標的名字獲得相應線程,調用目標線程的函數給目標發送信息
*/
if (users.containsKey(touser))// 加判斷,防止用戶已經離線
((UserThread) users.get(touser)).sendUser(MSG_FROM
+ this.username + NAME_END + msg);
}
}
/**
* 主方法:啟動服務器
*/
public static void main(String[] args) {
/*
* 根據參數的情況,獲得端口號,無效時使用默認值,并返回相應信息
*/
int port = Integer.parseInt(DEFAULT_PORT);
if (args.length > 0) {
int newport;
try {
newport = Integer.parseInt(args[0]);
/*
* 無效端口
*/
if (newport > 65535 || newport < 0) {
System.out.println("The port " + newport + " is invalid.");
}
/*
* 操作系統預留端口
*/
else if (newport <= 1024) {
System.out.println("The port 0~1024 is not allowed.");
} else {
port = newport;
}
}
/*
* 不能轉換成整數的參數
*/
catch (NumberFormatException e) {
System.out.println("Invalid port number!");
}
}
try {
ServerSocket ss = new ServerSocket(port);
System.out.print("Server is running.\nPort:" + port + "\nOnline:0");
while (true) {
Socket s = ss.accept();
Thread t = new UserThread(s);
t.start();
}
}
/*
* 端口綁定失敗
*/
catch (IOException e) {
System.out.println("Failed to bind " + port + "port.");
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -