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

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

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

计划包含:

  • 每当添加新客户端及其名称和位置时,都会通知每个客户。
  • 它还会检查现有名称。 程序不允许多个客户端使用相同的名称。

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

这是代码(有关更多说明,请参阅代码注释):

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

运行程序的步骤:

  • 首次只运行一次LiveChatServer
  • 然后为多个客户端运行LiveChatClient,尽可能多地添加

Opcode.java:

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

package com.chat; /**************** an interface to define different operation code **************/ public interface Opcode { int CLIENT_CONNECTEING = 1; int CLIENT_CONNECTED = 2; } 

LiveChatServer.java:

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

 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 clientInfo = new LinkedHashMap(); // 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 getClientInfo() { return clientInfo; } // *********************************** Main Method ******************** public static void main(String args[]) { new LiveChatServer(); } } 

LiveChatClient.java:

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

 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为每个客户端启动多个线程,并包含有关所有连接客户端的信息

 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 clientInfo = new HashMap(); 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); } } } 

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

服务器:

 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 

有2个线程,一个用于用户1,一个用于用户2.他们应该使用共享对象相互通信,并在事件发生时互相通知。 当第一个用户连接时产生线程1,当第二个用户连接时产生线程2。