具有多客户端通信的Java Server。

问题描述:

我正在为一项作业制作游戏。我有一个用Java设置的服务器和多客户端,我们正在使用MVC。我需要有一个客户端将他们的名字发送到服务器然后当两个玩家在场时我需要将两个名字一起发送回客户端以及他们是哪个玩家编号(玩家一或玩家二)。我不知道如何判断信息来自哪个线程或信息被发送到哪个线程,因此并非所有玩家都认为他们是玩家一。谢谢。

I'm making a game for an assignment. I have a server and multiclient set up in Java and we're using MVC. I need to have a client send their name to the server and then when two players are present I need to send both names back to the clients along with which player number they are (player one or player two). I don't get how I could tell which thread the information is coming from or which thread the information is getting sent to so not all players think they are player one. Thanks.

我在这里与大家分享一个很好的聊天程序,其中一台服务器与多个客户端进行通信根据您的要求使用TCP协议。

Here I am sharing you a nice Chat Program having one server that is communicating with multiple clients using TCP protocol as per your requirement.

程序包含:


  • 每个客户无论何时添加新客户及其姓名和职位,都会收到通知。

  • 它还会检查现有名称。程序不允许多个客户端使用相同的名称。

使用此程序作为游戏的初始启动程序。如果您想在程序中添加新功能,请告诉我。

Use this program as initial starter for your game. Please let me know if you want to add new functionality in the program.

以下是代码(请参阅代码注释以获得更多说明):

Here is the code (see code comments for more clarification):

注意:在端口号1234运行此程序之前替换LiveChatClient.java文件中的主机名

Note: replace host name in LiveChatClient.java file before running this program at port no 1234

步骤运行程序:


  • 首次运行LiveChatServer一次

  • 然后为多个客户端运行LiveChatClient您想要添加的数量

Opcode.java:

用于设置客户端 - 服务器通信协议的操作代码

Operation code that is used to set a client-server communication protocol

package com.chat;

/**************** an interface to define different operation code **************/

public interface Opcode {
    int CLIENT_CONNECTEING = 1;
    int CLIENT_CONNECTED = 2;
}

LiveChatServer.java:

控制多个客户的单个服务器

Single server that is controlling multiple clients

package com.chat;

/************************ Live Chat Server *******************/

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.LinkedHashMap;

public class LiveChatServer {

    // Connection state info
    private static LinkedHashMap<String, ClientThread> clientInfo = new LinkedHashMap<String, ClientThread>();

    // TCP Components
    private ServerSocket serverSocket;

    // Main Constructor
    public LiveChatServer() {

        startServer();// start the server
    }

    public void startServer() {
        String port = "1234";

        try {
            // in constractor we are passing port no, back log and bind address whick will be local
            // host
            // port no - the specified port, or 0 to use any free port.
            // backlog - the maximum length of the queue. use default if it is equal or less than 0
            // bindAddr - the local InetAddress the server will bind to

            int portNo = Integer.valueOf(port);
            serverSocket = new ServerSocket(portNo, 0, InetAddress.getLocalHost());
            System.out.println(serverSocket);

            System.out.println(serverSocket.getInetAddress().getHostName() + ":"
                    + serverSocket.getLocalPort());

            while (true) {
                Socket socket = serverSocket.accept();
                new ClientThread(socket);
            }
        } catch (IOException e) {
            System.out.println("IO Exception:" + e);
            System.exit(1);
        } catch (NumberFormatException e) {
            System.out.println("Number Format Exception:" + e);
            System.exit(1);
        }
    }

    public static HashMap<String, ClientThread> getClientInfo() {
        return clientInfo;
    }

    // *********************************** Main Method ********************

    public static void main(String args[]) {
        new LiveChatServer();
    }

}

LiveChatClient.java:

多个客户通过服务器相互通信

Multiple clients talking to each other via server

package com.chat;

/************************ Live Chat Client *******************/

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;

public class LiveChatClient {
    private String chatName;// current user's chat name(max 7 char if greater than show as 6
                            // char+...
    private String serverAddress;

    // TCP Components
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;

    public LiveChatClient() {

        initHostName();
        runClient();// have fun
    }

    public void initHostName() {
        try {
            //replace host name with your computer name or IP address
            serverAddress = "[hostname]";
            if (serverAddress == null)
                System.exit(1);

            serverAddress = serverAddress.trim();
            if (serverAddress.length() == 0)// empty field
            {
                System.out.println("Server IP Address or Name can't be blank.");
                initHostName();
                return;
            }
            System.out.println("Trying to connect with server...\nServer IP Address:"
                    + serverAddress);

            // create socket
            InetAddress inetAddress = InetAddress.getByName(serverAddress);
            if (!inetAddress.isReachable(60000))// 60 sec
            {
                System.out
                        .println("Error! Unable to connect with server.\nServer IP Address may be wrong.");
                System.exit(1);
            }

            initPortNo();
        } catch (SocketException e) {
            System.out.println("Socket Exception:\n" + e);
            initHostName();
            return;
        } catch (IOException e) {
            initHostName();
            return;
        }
    }

    public void initPortNo() {
        try {

            String portNo = "1234";

            portNo = portNo.trim();
            if (portNo.length() == 0)// empty field
            {
                System.out.println("Server port No can't be blank.");
                initPortNo();
                return;
            }
            System.out.println("Trying to connect with server...\nServer Port No:" + portNo);

            socket = new Socket(serverAddress, 1234);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream(), true);

        } catch (IOException e) {
            System.out.println("IO Exception:\n" + e);
            initPortNo();
            return;
        }
    }

    public void sendChatName() throws IOException {
        System.out.println("Enter your name:");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String name = br.readLine();
        if (name == null)
            System.exit(1);

        // title case (get only first 9 chars of chat name)
        name = name.trim();

        if (name.equalsIgnoreCase("All")) {
            System.out.println("This name is already reserved. Try different one.");
            sendChatName();
            return;
        }
        if (name.length() == 0) {
            System.out.println("Please enter your chat name.");
            sendChatName();
            return;
        }
        if (name.length() == 1)
            chatName = String.valueOf(name.charAt(0)).toUpperCase();
        if (name.length() > 1 && name.length() < 10)
            chatName = String.valueOf(name.charAt(0)).toUpperCase()
                    + name.substring(1).toLowerCase();
        else if (name.length() > 9)
            chatName = String.valueOf(name.charAt(0)).toUpperCase()
                    + name.substring(1, 10).toLowerCase();

        // sending opcode first then sending chatName to the server
        out.println(Opcode.CLIENT_CONNECTEING);
        out.println(chatName);
    }

    public void runClient() {
        try {
            sendChatName();
            while (true) {
                int opcode = Integer.parseInt(in.readLine());
                switch (opcode) {
                    case Opcode.CLIENT_CONNECTEING:
                        // this client is connecting
                        boolean result = Boolean.valueOf(in.readLine());
                        if (result) {
                            System.out
                                    .println(chatName + " is already present. Try different one.");
                            runClient();
                        }

                        break;

                    case Opcode.CLIENT_CONNECTED:
                        // a new client is connected
                        Integer totalClient = Integer.valueOf(in.readLine());
                        System.out.println("Total Client:" + totalClient);

                        for (int i = 0; i < totalClient; i++) {
                            String client = in.readLine();
                            System.out.println((i + 1) + ":" + client);
                        }

                        break;

                }
            }
        } catch (IOException e) {
            System.out.println("Client is closed...");
        }
    }

    // *********************************** Main Method ********************

    public static void main(String args[]) {
        new LiveChatClient();
    }

}

ClientThread.java:

多个线程由服务器1为每个客户端启动并包含有关所有连接客户端的信息

Multiple thread started by server one for each client and containing information about all connected clients

package com.chat;

/************************ Client Thread *******************/

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.HashMap;

public class ClientThread implements Runnable {
    // TCP Components
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;
    private String chatName;

    // seperate thread
    private Thread thread;

    // boolean variable to check that client is running or not
    private volatile boolean isRunning = true;

    // opcode
    private int opcode;
    private HashMap<String, ClientThread> clientInfo = new HashMap<String, ClientThread>();

    public ClientThread(Socket socket) {
        try {
            this.socket = socket;
            this.clientInfo = LiveChatServer.getClientInfo();

            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream(), true);

            thread = new Thread(this);
            thread.start();

        } catch (IOException e) {
            System.out.println(e);
        }
    }

    public void run() {
        try {
            while (isRunning) {
                if (!in.ready())
                    continue;

                opcode = Integer.parseInt(in.readLine());// getting opcode first from client
                switch (opcode) {
                    case Opcode.CLIENT_CONNECTEING:
                        chatName = in.readLine();

                        boolean result = clientInfo.containsKey(chatName);
                        out.println(Opcode.CLIENT_CONNECTEING);
                        out.println(result);
                        if (result)// wait for another chat name if already present
                            continue;

                        // send list of already online users to new online user
                        // for (Object user : clientInfo.keySet().toArray()) {
                        // out.println(Opcode.CLIENT_CONNECTED);
                        // out.println(user.toString());
                        // }

                        // put new entry in clientInfo hashmap
                        clientInfo.put(chatName, this);

                        int i = 0;
                        for (String key : clientInfo.keySet()) {
                            if (key.equals(chatName)) {
                                System.out.println(chatName + " added at " + (i + 1) + " position");
                            }
                            i++;
                        }

                        // tell other users about new added user and update their online users list
                        for (ClientThread client : clientInfo.values()) {
                            client.out.println(Opcode.CLIENT_CONNECTED);
                            client.out.println(clientInfo.size());

                            for (ClientThread client1 : clientInfo.values()) {
                                client.out.println(client1.chatName);
                            }
                        }

                        break;
                }
            }

            // clsoe all connections
            out.close();
            in.close();
            socket.close();
        } catch (IOException e) {
            System.out.println(e);
        }
    }
}

这是两个时的输出客户端已添加。

Here is the output when two client are added.

服务器:

ServerSocket[addr=computerName/IPAddress,port=0,localport=1234]
computerName:1234
Abc added at 1 position
Xyz added at 2 position

客户1:

Trying to connect with server...
Server IP Address:computerName
Trying to connect with server...
Server Port No:1234
Enter your name:
abc
Total Client:1
1:Abc
Total Client:2
1:Abc
2:Xyz

客户2:

Trying to connect with server...
Server IP Address:computerName
Trying to connect with server...
Server Port No:1234
Enter your name:
xyz
Total Client:2
1:Abc
2:Xyz