package edu.swpu.zhou;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
/**
* 显示服务器及用户信息的Panel类
*/
class MessageServerPanel extends Panel
{
TextArea messageBoard = new TextArea("", 22, 50,
TextArea.SCROLLBARS_VERTICAL_ONLY);
Label statusLabel = new Label("当前连接数:", Label.LEFT);
Panel boardPanel = new Panel();//主显示区Panel
Panel statusPanel = new Panel();//连接状态Panel
MessageServerPanel() {
setSize(350, 300);
setBackground(new Color(204,204,204));
setLayout(new BorderLayout());
boardPanel.setLayout(new FlowLayout());
boardPanel.setSize(210, 210);
statusPanel.setLayout(new BorderLayout());
statusPanel.setSize(210, 50);
boardPanel.add(messageBoard);
statusPanel.add(statusLabel, BorderLayout.WEST);
add(boardPanel, BorderLayout.CENTER);
add(statusPanel, BorderLayout.NORTH);
}
}
/**
* 服务器线程,主要用于服务器与客户端的通信
*/
class ServerThread extends Thread {
Socket clientSocket;
Hashtable clientDataHash;//Socket与发送数据的流的映射
Hashtable clientNameHash;//Socket与用户名的映射
Hashtable chessPeerHash;//对弈的两个客户端用户名的映射
MessageServerPanel server;
boolean isClientClosed = false;
/**
* 服务器端线程的构造函数,用于初始化一些对象。
*/
ServerThread(Socket clientSocket, Hashtable clientDataHash,
Hashtable clientNameHash, Hashtable chessPeerHash,
MessageServerPanel server) {
this.clientSocket = clientSocket;
this.clientDataHash = clientDataHash;
this.clientNameHash = clientNameHash;
this.chessPeerHash = chessPeerHash;
this.server = server;
}
/**
* 对客户端发来的消息处理的函数,处理后转发回客户端。处理消息的过程比较复杂,
* 要针对很多种情况分别处理。
*/
public void messageTransfer(String message) {
String clientName, peerName;
//如果消息以“/”开头,表明是命令消息。
if (message.startsWith("/")) {
//消息以“/changename”开头的几种情况.
if (message.startsWith("/changename ")) {
//获取修改后的用户名
clientName = message.substring(12);
if (clientName.length() <= 0 || clientName.length() > 20
|| clientName.startsWith("/")
|| clientNameHash.containsValue(clientName)
|| clientName.startsWith("changename")
|| clientName.startsWith("list")
|| clientName.startsWith("[inchess]")
|| clientName.startsWith("creatgame")
|| clientName.startsWith("joingame")
|| clientName.startsWith("yourname")
|| clientName.startsWith("userlist")
|| clientName.startsWith("chess")
|| clientName.startsWith("OK")
|| clientName.startsWith("reject")
|| clientName.startsWith("peer")
|| clientName.startsWith("peername")
|| clientName.startsWith("giveup")
|| clientName.startsWith("youwin")
|| clientName.startsWith("所有人")) {
//如果名字不合规则,则向客户端发送信息“无效命令”。
message = "无效命令";
Feedback(message);
} else {
if (clientNameHash
.containsValue(("[inchess]" + (String) clientNameHash
.get(clientSocket)))) {
//如果用户正在对弈中,则直接修改Socket和名字的映射Hash表。
synchronized (clientNameHash) {
clientNameHash.put((Socket) getHashKey(
clientNameHash,
("[inchess]" + clientNameHash
.get(clientSocket))),
("[inchess]" + clientName));
chessPeerTalk(("[inchess" + clientName),
("/yourname " + ("[inchess]" + clientName)));
}
}
//如果用户在对弈双方的客户端,做如下处理。
else if (chessPeerHash.containsKey(clientNameHash
.get(clientSocket))) {
//将客户端的新名字映射到clientNameHash
synchronized (clientNameHash) {
clientNameHash.put((Socket) getHashKey(
clientNameHash,
("[inchess]" + clientNameHash
.get(clientSocket))),
("[inchess]" + clientName));
}
synchronized (chessPeerHash) {
//chessPeerHash添加新名字映射
chessPeerHash.put(clientName, chessPeerHash
.get(clientNameHash.get(clientSocket)));
//chessPeerHash删除旧映射
chessPeerHash.remove(clientNameHash
.get(clientSocket));
}
//向游戏客户端发送新名字
chessPeerTalk(("[inchess]" + clientName),
("/yourname " + ("[inchess]" + clientName)));
//向peer游戏客户端发送
chessPeerTalk((String) chessPeerHash.get(clientName),
("/peer " + "[inchess]" + clientName));
}
// 如果用户在对弈双方的服务端,做如下处理。
else if (chessPeerHash.containsValue(clientNameHash
.get(clientSocket))) {
synchronized (clientNameHash) {
//游戏客户端改名字
clientNameHash.put((Socket) getHashKey(
clientNameHash,
("[inchess]" + clientNameHash
.get(clientSocket))),
("[inchess]" + clientName));
}
synchronized (chessPeerHash) {
//chessPeerHash重新映射
chessPeerHash.put((String) getHashKey(
chessPeerHash, clientNameHash
.get(clientSocket)), clientName);
//向游戏客户端发送新名字
chessPeerTalk(("[inchess]" + clientName),
("/yourname " + ("[inchess]" + clientName)));
}
//向peer游戏客户端发送
chessPeerTalk((String) getHashKey(chessPeerHash,
clientName),
("/peer " + "[inchess]" + clientName));
}
//将改名消息封装好以备发送
message = clientNameHash.get(clientSocket) + "改名为:"
+ clientName;
synchronized (clientNameHash) {
clientNameHash.put(clientSocket, clientName);
}
//向所有的客户端发送消息
publicTalk(message);
//回馈到改名的客户端
Feedback("/yourname "
+ (String) clientNameHash.get(clientSocket));
//刷新用户列表
publicTalk(getUserList());
}
}
//如果消息以“/list”开头,则将其回馈到客户端以更新用户列表
else if (message.equals("/list")) {
Feedback(getUserList());
}
//如果消息以"/creatgame [inchess]"开头,则修改clientNameHash映射
//和chessPeerHash映射。
else if (message.startsWith("/creatgame [inchess]")) {
String chessServerName = message.substring(20);
synchronized (clientNameHash) {
clientNameHash.put(clientSocket, message.substring(11));
}
synchronized (chessPeerHash) {
chessPeerHash.put(chessServerName, "wait");
}
Feedback("/yourname " + clientNameHash.get(clientSocket));
chessPeerTalk(chessServerName, "/OK");
publicTalk(getUserList());
}
//如果消息以“/joingame”开头,则将消息的服务端名字和本地用户名提取出来,
//然后修改clientNameHash表和chessPeerHash表。
else if (message.startsWith("/joingame ")) {
StringTokenizer userToken = new StringTokenizer(message, " ");
String getUserToken, serverName, selfName;
String[] chessNameOpt = { "0", "0" };
int getOptNum = 0;
//提取服务端用户名和本地用户名
while (userToken.hasMoreTokens()) {
getUserToken = (String) userToken.nextToken(" ");
if (getOptNum >= 1 && getOptNum <= 2) {
chessNameOpt[getOptNum - 1] = getUserToken;
}
getOptNum++;
}
serverName = chessNameOpt[0];
selfName = chessNameOpt[1];
//如果有服务端在等待开始棋局
if (chessPeerHash.containsKey(serverName)
&& chessPeerHash.get(serverName).equals("wait")) {
//修改Socket和名字映射
synchronized (clientNameHash) {
clientNameHash.put(clientSocket,
("[inchess]" + selfName));
}
//修改chessPeerHash映射
synchronized (chessPeerHash) {
chessPeerHash.put(serverName, selfName);
}
publicTalk(getUserList());
chessPeerTalk(selfName,
("/peer " + "[inchess]" + serverName));
chessPeerTalk(serverName,
("/peer " + "[inchess]" + selfName));
} else {
评论12