管理基于文本的客户端-服务器连接的最佳方法是什么?

发布于 2024-11-02 05:00:48 字数 580 浏览 4 评论 0原文

我正在寻找编写一个基于客户端服务器的小型文本游戏,它可以处理多个客户端连接并持续影响游戏状态。我想知道处理多个连接的最佳方法是什么,以便命令按照到达服务器的顺序进行处理。

理想情况下,我不希望利用多线程,至少在命令处理级别上。我可以接受每个客户端都有一个单独的线程(以便在每个线程上阻塞 IO),只要我之后可以在单个线程中统一处理。

由于客户端和服务器之间的唯一通信是文本,因此我不确定如何最好地设置通信。如果我选择阻塞 IO,我将如何让处理在单个线程中进行排队?

或者,如果我选择非阻塞 IO 并使用选择器来查询客户端何时写入服务器,那么如何在不使用设置大小的 ByteBuffer 的情况下读取未知/无限长度的字符串?非阻塞也有利于将处理保持在单个线程中,因为它可以在客户端连接发送新数据时从客户端连接中读取数据。然而,当我尝试用 read/writeUTF 实现它时,我遇到了 IllegalBlockingModeException 呵呵。

对于如何以我未提及的方式执行此操作的任何问题的答案或建议,我们将不胜感激!我对客户端和服务器相当陌生,所以我不知道 java.io 还是 java.nio 是否最合适。

很抱歉问了这个复杂的问题。我想我是自己逃跑了。

I'm looking to write a small client-server-based text game that handles multiple client connections and persistently affects a game state. I'm wondering what the best way would be to handle multiple connects such that commands are processed in the order they arrive at the server.

Ideally I'm not looking to take advantage of multi-threading, at least on the command processing level. I would be okay with each client having a separate thread (in order to have blocking IO on each thread), as long as I could unify the processing in a single thread thereafter.

Since the only communication between the client and server will be text, I'm not sure how best to go about setting up the communication. If I chose blocking IO, how would I get queue the processing to occur in a single thread?

Alternatively, if I choose non-blocking IO and use a selector to query for when clients have written to the server, how can I get read a String of unknown/unlimited length without using a set-size ByteBuffer? Non-blocking also favours keeping the processing in a single thread as it can just read from the client connections as and when they send new data. However, when I tried to implement it with read/writeUTF I came up against the IllegalBlockingModeException heh.

Any answers to the questions or suggestions on how to do this in a way I haven't mentioned would be sincerely appreciated! I'm fairly new to clients and servers so I don't know whether java.io or java.nio would be most appropriate.

Sorry for the convoluted question. I think I ran away with myself.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

待天淡蓝洁白时 2024-11-09 05:00:48

意见不同,但我肯定会为每个客户端使用一个线程。然后,与单个处理线程的通信可以通过 LinkedBlockingQueue 或仅通过同步 LinkedList 进行。

在每个客户端线程上类似这样:

public class Client implements Runnable, ResponseOutput {

    private final BufferedReader br;
    private final PrintWriter pw;

    public Client(Socket s) {
        br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        pw = new PrintWriter(s.getOutputStream());
    }

    // defined by the ResponseOutput interface
    public void sendReply(String reply) {
        pw.println(reply);
    }

    public void run() {
        try {
            while (true) {
                String s = br.readLine();
                if (s==null)
                    break;
                Processor.queue(new Processor.InputItem(this, s));
            }
        } catch (IOException ioe) {
            ... error handling ...
        }
    }
}

然后进行处理:

public class Processor implements Runnable {
    static public class InputItem {
        final ResponseOutput client;
        final String command;

        public InputItem(ResponseOutput client, String command) {
            this.client = client;
            this.command = command;
        }
    }

    static private Processor instance;
    static public void queue(InputItem item) {
        instance.commandQueue.add(item);
    }

    private BlockingQueue<InputItem> commandQueue;

    public void run() {
        try {
            while (true) {
                InputItem item = commandQueue.take();
                String reply = doStuff(item.command);
                item.client.sendReply(reply);
            }
        } catch (InterruptedException ie) {
            ... error handling ....
        }
    }
}

InputItem 类中,您还可以包含对任何需要更新的游戏状态的引用。由于只有处理线程会更改它,因此您无需任何同步即可完成此操作。

Opinions differ, but I'd definitely go with a single thread per client. The communication to the single processing thread could then go via a LinkedBlockingQueue, or just a synchronized LinkedList.

Something like this on the per-client thread:

public class Client implements Runnable, ResponseOutput {

    private final BufferedReader br;
    private final PrintWriter pw;

    public Client(Socket s) {
        br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        pw = new PrintWriter(s.getOutputStream());
    }

    // defined by the ResponseOutput interface
    public void sendReply(String reply) {
        pw.println(reply);
    }

    public void run() {
        try {
            while (true) {
                String s = br.readLine();
                if (s==null)
                    break;
                Processor.queue(new Processor.InputItem(this, s));
            }
        } catch (IOException ioe) {
            ... error handling ...
        }
    }
}

Then this for the processing:

public class Processor implements Runnable {
    static public class InputItem {
        final ResponseOutput client;
        final String command;

        public InputItem(ResponseOutput client, String command) {
            this.client = client;
            this.command = command;
        }
    }

    static private Processor instance;
    static public void queue(InputItem item) {
        instance.commandQueue.add(item);
    }

    private BlockingQueue<InputItem> commandQueue;

    public void run() {
        try {
            while (true) {
                InputItem item = commandQueue.take();
                String reply = doStuff(item.command);
                item.client.sendReply(reply);
            }
        } catch (InterruptedException ie) {
            ... error handling ....
        }
    }
}

Within the InputItem class, you can also include a reference to any game state that needs updating. Since there's only the processing thread changing it, you get to do that without any synchronization.

慵挽 2024-11-09 05:00:48

我不是服务器客户端系统方面的专家,但我将分享一些技巧,

根据您的需要,您可以简单地设置一个 Tomcat 服务器并执行 http 请求,它相当简单,当然全部都是用 Java 编写的。

缺点是请求可能有点慢。

您可以检查的第二个选项是 RMI。

这个概念很简单,您连接到另一台计算机,完成后,您可以从代码中的本地对象调用另一台计算机上的方法。

http://java.sun.com/developer/onlineTraining/rmi/RMI.html

它可能看起来有点复杂(有时通过多台计算机调试堆栈有点棘手),但我推荐,因为它可以使您的代码保持清晰。

最后你可以尝试套接字,但你自己:P

i'm no expert in sever client systems but I'll share a couple of tips

Depending on your need you could simply set up a Tomcat server and do http request, its fairly straight forwards and of course all in Java.

the downside is that the request might be a bit slow.

The Second option you can check out is RMI.

The concept is simple you connect to another computer and when that is done you call methods on the other computer from a local object in you code.

http://java.sun.com/developer/onlineTraining/rmi/RMI.html

it might look a bit complicated (and sometimes debbuging a stack through multiple computer is a bit tricky) but I recommend because it keeps your code clear.

Finally you can try sockets but there your on your own :P

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文