⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chessserver.java

📁 实现了一个网络五子棋的对弈程序
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package server;

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("/")) {

            // 如果消息以“/list”开头,则将其回馈到客户端以更新用户列表
            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表。
            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 {
                    chessPeerTalk(selfName, "/reject");
                    try {
                        clientClose();
                    } catch (Exception ez) {
                    }
                }
            }
            // 如果消息以“/[inchess]”开头,则获取要发送消息的用户名和发送的消息
            // 然后发送出去。
            else if (message.startsWith("/[inchess]")) {
                int firstLocation = 0, lastLocation;

                lastLocation = message.indexOf(" ", 0);

                peerName = message.substring((firstLocation + 1), lastLocation);
                message = message.substring((lastLocation + 1));
                if (chessPeerTalk(peerName, message)) {
                    Feedback("/error");
                }
            }
            // 如果消息以“/giveup”开头,则判断是对弈双方哪方放弃了。
            else if (message.startsWith("/giveup ")) {
                String chessClientName = message.substring(8);
                if (chessPeerHash.containsKey(chessClientName)
                        && !((String) chessPeerHash.get(chessClientName)).equals("wait")) {
                    // 如果服务方放弃,则发送消息“/youwin”表明对方获胜
                    chessPeerTalk((String) chessPeerHash.get(chessClientName), "/youwin");
                    //剔除这对对弈的人。。
                    synchronized (chessPeerHash) {
                        chessPeerHash.remove(chessClientName);
                    }
                }
                if (chessPeerHash.containsValue(chessClientName)) {
                    // 如果客户方放弃,也发送消息“/youwin”表明对方获胜
                    chessPeerTalk((String) getHashKey(chessPeerHash, chessClientName), "/youwin");
                    synchronized (chessPeerHash) {
                        chessPeerHash.remove((String) getHashKey(chessPeerHash, chessClientName));
                    }
                }
            }
            // 如果找不到发送消息的用户,则输出消息说“没有这个用户”
            else {
                int firstLocation = 0, lastLocation;
                lastLocation = message.indexOf(" ", 0);
                if (lastLocation == -1) {
                    Feedback("无效命令");
                    return;
                } else {
                    peerName = message.substring((firstLocation + 1), lastLocation);
                    message = message.substring((lastLocation + 1));
                    message = (String) clientNameHash.get(clientSocket) + ">" + message;
                    if (peerTalk(peerName, message)) {
                        Feedback("没有这个用户:" + peerName + "\n");
                    }
                }

            }

        }
        // //////////////////////////////////////////////
        // 如果不以“/”开头,表明是普通消息,直接发送
        else {
            message = clientNameHash.get(clientSocket) + ">" + message;
            server.messageBoard.append(message + "\n");
            publicTalk(message);
            server.messageBoard.setCaretPosition(server.messageBoard.getText().length());
        }

    }

    /**
     * 发送公共消息的函数,将消息向每个客户端都发送一份
     */
    public void publicTalk(String publicTalkMessage) {

        synchronized (clientDataHash) {
            //枚举遍历所有客户端输出流。。
            for (Enumeration enu = clientDataHash.elements(); enu.hasMoreElements();) {
                DataOutputStream outData = (DataOutputStream) enu.nextElement();
                try {
                    //输出信息。。这里会阻塞
                    outData.writeUTF(publicTalkMessage);
                } catch (IOException es) {
                    //打印异常堆栈。。。终止程序。。
                    es.printStackTrace();
                }
            }
        }
    }

    /**
     * 选择对象发送消息,参数peerTalk为发送的用户名,后面的参数为发送的消息
     */
    public boolean peerTalk(String peerTalk, String talkMessage) {
        //
        for (Enumeration enu = clientDataHash.keys(); enu.hasMoreElements();) {
            Socket userClient = (Socket) enu.nextElement();
            // 找到发送消息的对象,获取它的输出流以发送消息
            if (peerTalk.equals((String) clientNameHash.get(userClient))
                    && !peerTalk.equals((String) clientNameHash.get(clientSocket))) {
                synchronized (clientDataHash) {
                    DataOutputStream peerOutData = (DataOutputStream) clientDataHash.get(userClient);
                    try {
                        peerOutData.writeUTF(talkMessage);
                    } catch (IOException es) {
                        es.printStackTrace();
                    }
                }
                Feedback(talkMessage);
                return (false);
            }
            // 如果是发给自己的,直接回馈
            else if (peerTalk.equals((String) clientNameHash.get(clientSocket))) {
                Feedback(talkMessage);
                return (false);
            }
        }

        return (true);

    }

    /**
     * 此函数也用于选择发送消息,但不能发送给自己。
     */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -