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