具有多客户端通信的Java Server

如何解决具有多客户端通信的Java Server

在这里,我与您分享了一个不错的 ,其中包含一台服务器,该服务器根据您的要求使用TCP协议与多个客户端进行通信。

程序包含:

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

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

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

在端口号1234上运行此程序之前,请先替换LiveChatClient.java文件中的主机名。

运行程序的步骤:

  • 第一次只运行LiveChatServer
  • 然后为要添加的多个客户端运行LiveChatClient

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

package com.chat;

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

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

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

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

}

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

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

}

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

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

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

服务器:

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

解决方法

我正在为任务做游戏。我有一个用Java设置的服务器和多客户端,我们正在使用MVC。我需要有一个客户端将其名称发送到服务器,然后当有两个玩家出现时,我需要将这两个名称以及他们的玩家编号(玩家1或玩家2)发送回客户端。我不知道如何分辨信息来自哪个线程或信息被发送到哪个线程,因此并非所有玩家都认为自己是玩家之一。谢谢。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-