【问题标题】:Client program that can connect to multiple servers simultaneously可以同时连接多个服务器的客户端程序
【发布时间】:2014-02-24 01:25:18
【问题描述】:

我使用 JAVA 中的套接字编程编写了一个基本的服务器客户端程序。服务器是多线程的,可以一次接受多个客户端连接。然而,客户端不是多线程的。客户端可以从服务器上传、下载、读取、写入和删除文件。我在命令提示符窗口中运行这些程序,因此它们没有任何外部用户界面。到目前为止,我的程序运行良好。

我现在想让客户端也多线程,以便它可以同时连接到多个服务器。然后我希望客户端能够向服务器发送请求。客户端可以在它可能连接的众多服务器中选择将请求发送到哪个服务器。

考虑到这一点,我将客户端代码更改为具有多个线程。但是我不知道如何在程序运行时在服务器之间进行选择。有没有办法在JAVA中(程序运行时)随意切换线程,以便我可以选择哪个线程处理我的请求?

【问题讨论】:

  • 所以你打算让客户端连接到的每台服务器都有一个线程?您可以给每个线程一个阻塞的请求队列来处理,并让用户线程将作业放在这些队列上。但是没有理由每个服务器都需要一个线程。您只需要尽可能多的线程来执行同时操作符,因此如果它只是一个可选择服务器的操作,则不需要多个线程。或者,您可以在执行器池中使用少量线程来对您的服务器连接集执行操作。
  • 例如,如果我将客户端连接到三台服务器,那么客户端将自动需要至少三个线程,对吧?
  • 不一定,尽管在实践中它可能取决于您使用的协议以及您发出的操作可能会阻塞多长时间。没有理由单个线程不能监视许多 TCP 连接并异步响应它们。但是每个客户端连接一个线程可以很好地工作,而且(通常)线程很便宜。
  • 那么我如何在客户端程序的线程之间切换?客户端程序可能连接到 server1 和 server2。它可能想现在向服务器 1 发送读取文件请求,稍后向服务器 2 发送下载请求。我如何在 Java 中指定哪个服务器获取下载请求,哪个服务器获取读取请求,同时保持两个服务器的连接处于活动状态和持久性,以便在这些操作完成后,客户端可以再次向两个服务器中的任何一个发送附加请求?
  • 从这个意义上说,您不会切换。线程独立运行;您需要想出一种方法来向他们传递指令,并让他们将结果、进度等传递回您的主线程/UI 线程。

标签: java multithreading sockets


【解决方案1】:

这里有一些你可以如何做到这一点的骨架:

public class Client {

    public static void main(String[] args) {

         Connection w1 = new Connection("localhost", 2346);
         w1.start();

         Connection w2 = new Connection("localhost", 2346);
         w2.start();

         Connection w3 = new Connection("localhost", 2347);
         w3.start();

         w1.sendMessage("Hello ");
         w2.sendMessage("Coffee ");
         w1.sendMessage("world!");
         w2.sendMessage("break!");
         w3.sendMessage("Beer!");

         w1.terminate();
         w2.terminate();
         w3.terminate();
    }
}

只要你不使用忙等待它来处理新线程中的每个连接:

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.concurrent.ConcurrentLinkedQueue;

public class Connection implements Runnable {

    private String host;
    private int port;
    private PrintWriter os;

    private volatile boolean running = false;
    private ConcurrentLinkedQueue<String> queue;

    public Connection(String host, int port) {
        this.host = host;
        this.port = port;
        this.queue = new ConcurrentLinkedQueue<String>();
    };

    public void start() {
        try {
            this.os = new PrintWriter(new Socket(host, port).getOutputStream());
        } catch (IOException e) {
            return;
        }

        running = true;
        new Thread(this).start();
    }

    @Override
    public void run() {

        while(running) {
            // send messages in queue
            while(!queue.isEmpty()) {
                os.print(queue.poll());
            }
            // wait to be notified about new messages
            try {
                this.wait();
            } catch (InterruptedException e) {
                terminate();
            }
        }
    }

    public synchronized void sendMessage(String msg) {
        queue.add(msg);
        this.notify();
    }

    public void terminate() {
        running = false;
    }

    public boolean isRunning() {
        return running;
    }
}

【讨论】:

    猜你喜欢
    • 2015-06-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-17
    • 2015-03-21
    • 1970-01-01
    • 2011-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多