import java.net.*;
//import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
//import java.util.Map;
import java.io.*;
public
class Server {
List<ClientServer> allClients =
new LinkedList<ClientServer>();
ServerSocket server =
null;
boolean started =
false;
ClientListenner cl =
null;
//////////////////////////客戶端Control + C 時發生NullPointerException,在線程ClientServer處
public
static
void main(String[] args) {
new Server().start();
}
/*
* 服務器端構造函數
* 將監聽接口綁定到本地端口8888處
*/
public Server(){
try {
server =
new ServerSocket(8888);
}
catch (BindException e) {
System.out.println(
"端口使用中");
System.out.println(
"請關掉相關程序並從新運行服務器!");
System.exit(0);
}
catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
}
/*
* 服務器啓動函數
*/
public
void start() {
System.out.println(
"Server Starts!");
started =
true;
cl =
new ClientListenner(server);
cl.start();
readCommand();
}
/*
* 服務器關閉函數
*/
public
void shutdown() {
started =
false;
cl.close();
System.out.println(
"server shutdown");
}
/*
* 讀取控制檯輸入命令函數
*/
public
void readCommand() {
BufferedReader br =
new BufferedReader(
new InputStreamReader(System.in));
String str =
null;
try{
while(started){
str = br.readLine();
excuteCommand(str);
}
}
catch (NullPointerException e){/////////////Control+C時發生的異常
System.out.println(
"服務器中斷");
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try{
br.close();
}
catch (IOException e1){
e1.printStackTrace();
}
}
}
/*
* 執行控制檯命令函數
*/
public
void excuteCommand(String command) {
if (command.toLowerCase().equals(
"useramount")) {
System.out.println(getUserAmount());
}
else
if (command.toLowerCase().equals(
"usernames")) {
System.out.println(getAllUserName());
}
else
if (command.toLowerCase().equals(
"userinfo")) {
System.out.println(getUserInfo());
}
else
if (command.toLowerCase().equals(
"help")) {
System.out.println(getHelp());
}
else
if (command.toLowerCase().equals(
"shutdown")){
shutdown();
}
}
/*
* 獲取當前服務器在線人數函數
*/
public String getUserAmount() {
return
"當前在線用戶人數爲: " + allClients.size() +
"\n";
}
/*
* 獲取當前服務器在線用戶的名字
*/
public String getAllUserName(){
StringBuffer sb =
new StringBuffer();
sb.append(
"當前在線用戶是:");
sb.append(
"\n");
for (
int i = 0; i < allClients.size(); i++) {
sb.append(allClients.get(i).userName);
}
return sb.toString();
}
/*
* 獲取當前服務器在線用戶的信息
* 包括用戶個數和用戶姓名
*/
public String getUserInfo() {
StringBuffer sb =
new StringBuffer();
sb.append(getUserAmount());
sb.append(getAllUserName());
return sb.toString();
}
/*
* 提供服務器命令信息
*/
public String getHelp() {
StringBuffer sb =
new StringBuffer();
sb.append(
"useramount 顯示當前在線用戶人數\n");
sb.append(
"usernames 顯示當前在線用戶的名字\n");
sb.append(
"userinfo 顯示當前在線用戶的人數及姓名");
return sb.toString();
}
/*
* 監聽客戶端鏈接線程
* 爲每個新鏈接的客戶端提供一個服務器線程
*/
class ClientListenner
extends Thread {
ServerSocket s =
null;
public ClientListenner(ServerSocket s) {
this.s = s;
}
@Override
public
void run() {
try{
while (started) {
Socket c_server = s.accept();
ClientServer cs =
new ClientServer(c_server);
allClients.add(cs);
System.out.println(cs.userName +
"登陸");
new Thread(cs).start();
}
}
catch (SocketException e){
System.out.print("");//////////////////客戶端關閉的時候發生異常
}
catch (IOException e){
e.printStackTrace();
}
}
public
void close() {
try {
started =
false;
if (s !=
null)
s.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
/*
* 服務器服務線程類
* 接受客戶端的輸入,並將得到到信息發送到全部的客戶端
*/
class ClientServer
implements Runnable {
Socket c_server =
null;
ClientServer cs =
null;
boolean connected =
false;
DataOutputStream dout =
null;
DataInputStream din =
null;
String userName =
null;
/*
* 構造函數
* 初始化從客戶端得到的socket、創建服務器與客戶端的鏈接、初始化輸入輸出流
*/
public ClientServer(Socket s) {
c_server = s;
connected =
true;
try {
din =
new DataInputStream(s.getInputStream());
dout =
new DataOutputStream(s.getOutputStream());
}
catch (IOException e) {
e.printStackTrace();
}
register(receiveMessage());
}
/*
* 消息發送函數
* 向客戶端發送消息
*/
public
void sendMessage(String message) {
try {
dout.writeUTF(message);
dout.flush();
}
catch (IOException e) {
e.printStackTrace();
}
}
/*
* 消息接受函數
* 從客戶端接受消息
*/
public String receiveMessage() {
String message =
null;
try{
message = din.readUTF();
}
catch (EOFException e){
System.out.println(
"客戶端中斷!");
}
catch (SocketException e){
System.out.print("");//////////////////客戶端關閉的時候發生異常
}
catch (IOException e){
e.printStackTrace();
}
return message;
}
@Override
public
void run() {
String str =
null;
sendMessage(
"server says:hello,I am the server!");
while (connected) {
str = receiveMessage();
interpret(str);
}
close();
}
/*
* 服務線程類關閉函數
* 關閉相關輸入輸出流、socket
*/
public
void close() {
try {
if (dout !=
null)
dout.close();
if (din !=
null)
din.close();
if (c_server !=
null)
c_server.close();
if (allClients.contains(
this))
allClients.remove(
this);
}
catch (IOException e) {
e.printStackTrace();
}
}
/*
* 消息解釋函數
* 根據消息類型選擇執行相關操做
*/
public
void interpret(String str) {
boolean bToAll =
true;
switch (strType(str)) {
case 0:
sendToClient(bToAll, str);
break;
case 1:
bToAll = changePeople(str);
break;
case 2:
excuteUserCommand(str);
break;
default:
break;
}
}
/*
* 註冊函數
* 服務器段記錄登陸用戶名
*/
private
void register(String name){
userName = name;
}
/*
* 命令執行函數
* 根據客戶端發送過來的指令執行相關操做
*/
private
void excuteUserCommand(String str){
String command = str.substring(1);
if (command.equals(
"userinfo")){
sendMessage(getUserInfo());
}
else
if(command.equals(
"help")){
sendMessage(getHelp());
}
else
if(command.equals(
"bye")){
connected =
false;
System.out.println(userName +
"退出了");
allClients.remove(
this);
}
}
/*
* 消息轉發對象轉換函數
* 選擇單對單發送消息,或者羣發消息
*/
private
boolean changePeople(String str) {
String name = str.substring(1);
if (name.equals(
"all")) {
return
true;
}
else {
for (
int i = 0; i < allClients.size(); i++) {
if (name.equals(allClients.get(i).userName)) {
cs = allClients.get(i);
return
false;
}
}
}
return
true;
}
/*
* 消息解釋函數
* 根據消息起始字符調用返回整型值
* @return 1 表示對象轉換
* @return 2 表示獲取服務器信息
* @return 0 表示正常消息發送語句
*/
private
int strType(String str){
if (str.startsWith(
"-"))
return 1;
else
if(str.startsWith(
"?"))
return 2;
else
return 0;
}
/*
* 消息發送函數
* 根據傳入的參數,將消息傳給羣發或者發送給指定客戶端
*/
private
void sendToClient(
boolean bToAll,String str) {
if (bToAll) {
for (
int i = 0; i < allClients.size(); i++) {
allClients.get(i).sendMessage(
this.userName +
" says: " + str);
}
}
else {
cs.sendMessage(cs.userName +
" says: " + str); } } } }