【问题标题】:How to connect multiple servers to a client in Java using Sockets?如何使用套接字将多个服务器连接到 Java 中的客户端?
【发布时间】:2019-03-23 23:45:41
【问题描述】:

我正在通过套接字做一个程序,从单个客户端到多个服务器,在互联网上我没有找到有关此的信息

该系统由将多个服务器连接到单个客户端组成,客户端必须向用户请求一个数字,然后在服务器中,使用该数字执行一个算法,该算法将找到介于 0 和N ,之后计算算法的执行时间,然后发送给客户端。每个服务器的每次发送到客户端,客户端存储它们。

问题在于,除了要同步此连接之外,此连接还必须在所需数量的服务器之间同时进行。

目前,我已经做了一个简单的代码,从客户端到服务器。

主服务器

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Server s = new Server(5000, "Hilo servidor");
    s.start();
    }

}

模块服务器

这是一个在服务器类内部的方法,这个类执行算法来计算有多少堂兄弟,并将那个时间发送给客户端。在主服务器调用c.start()时运行

private void startServer() {

            try {
                ServerSocket ss = new ServerSocket(port);
                System.out.println("Esperando Conexion");
                Socket socket = ss.accept();


                DataInputStream in = new DataInputStream(socket.getInputStream());
                int n = in.readInt();
                long time = encontrarPrimeros(n);
                DataOutputStream out = new DataOutputStream(socket.getOutputStream());
                out.writeLong(time);
                System.out.println(time);
            } catch (IOException ex) {
                Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
            }
}

主要客户

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
            Client c = new Client("Hilo cliente", 5000, "192.168.0.19");
            c.start();
    }

}

模块客户端

    private void startClient() {
            try {
                    Socket socket = new Socket(ip, port); 
                    DataOutputStream out = new DataOutputStream(socket.getOutputStream());


                    System.out.println("Ingrese dato...");
                    Scanner scanner = new Scanner(System.in);
                    int n = scanner.nextInt();
                    out.writeInt(n);
                    DataInputStream in = new DataInputStream(socket.getInputStream());
                    long tiempo = in.readLong();
                    System.out.println(tiempo);
                    socket.close();
            } catch (IOException ex) {
                    Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            }
    }

问题是,如何将多个服务器连接到一个客户端,以便它们开始同步?

谢谢

更新

我修改了客户端的main方法,原因如下:

public class Main {

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    Client c = new Client("Hilo cliente", 5000, "192.168.0.19");
    Client c2 = new Client("Hilo cliente", 5000, "192.168.0.19");
    c.start();
    c2.start();
}

}

但是在执行的时候出现如下错误:

mar 23, 2019 7:14:10 PM Client startClient
GRAVE: null
java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:210)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at java.io.DataInputStream.readFully(DataInputStream.java:195)
    at java.io.DataInputStream.readLong(DataInputStream.java:416)
    at Client.startClient(Client.java:69)
    at Client.run(Client.java:41)
    at java.lang.Thread.run(Thread.java:748)

执行错误的指令如下:long tiempo = in.readLong();

【问题讨论】:

  • 它是什么?根据您的标题,单个服务器,多个客户端?还是单个客户端,多个服务器,根据您的问题?
  • @user207421 一个客户端,多个服务器连接到该客户端
  • 对不起,标题已经更正了

标签: java sockets tcp


【解决方案1】:

其实在socket编程中:

  • 一个客户端只能连接到一个服务器
  • 服务器可以接收许多客户端连接
  • 客户端通过套接字对象管理其与服务器的连接

如果您的客户端需要连接到许多服务器,则客户端必须创建与服务器数量一样多的套接字对象。为了并行管理通信,您可以创建一个单独的线程来管理每个套接字的 IO。

因此应用于您的场景:

  • 您可以保留 Client 类,因为它管理一个套接字
  • 您在服务器数量中创建了 N 个 Client 对象(您将每个 Client 实例仅与一台服务器关联)
  • 您可以使您的 Client 类可运行(通过从 Thread 类继承)。
  • 您将 Client 作为线程运行(您可以将 startClient() 类放在从 Thread 继承的受保护的 void run() 方法中)。
  • 在您的主程序中,您调用每个客户端对象的 start() 方法(从线程继承)。这将在后台运行 run() 方法。
  • 要收集所有结果,请在每个 Client 对象上调用 join()

客户端类示例

    public class Client extends Thread {

    private String ip;
    private int port;


    public Client(String serverIP, int serverPort) {
        this.ip = new String(serverIP);
        this.port = serverPort;
    }

    private void startClient() {
        try {
            Socket socket = new Socket(ip, port); 
            DataOutputStream out = new DataOutputStream(socket.getOutputStream());

            System.out.println("Ingrese dato...");
            Scanner scanner = new Scanner(System.in);
            int n = scanner.nextInt();
            out.writeInt(n);
            DataInputStream in = new DataInputStream(socket.getInputStream());
            long tiempo = in.readLong();
            System.out.println(tiempo);
            socket.close();
        } catch (IOException ex) {
            ex.getStackTrace();
        }
    }

    @Override
    public void run() {

        startClient();

        super.run();
    }
}

主要

Client client1 = new Client("192.168.1.100", 8888);
    Client client2 = new Client("192.168.1.101", 8888);
    Client client3 = new Client("192.168.1.102", 8888);

    client1.start();
    client2.start();
    client3.start();

    try {
        client1.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    try {
        client2.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    try {
        client3.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

服务器类

public class Server extends Thread {


ExecutorService threadPool = Executors.newCachedThreadPool();

//Private class
class ClientSocket implements Runnable {

    private Socket m_socket;

    ClientSocket(Socket sock) {
        m_socket = sock;
    }

    @Override
    public void run() {
        try {
            DataInputStream in = new DataInputStream(m_socket.getInputStream());
            int n = in.readInt();
            long time = n;
            DataOutputStream out = new DataOutputStream(m_socket.getOutputStream());
            out.writeLong(time);
            out.flush();
            System.out.println(time);
            System.out.flush();
        } catch (IOException ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}


@Override
public void run() {
    startServer();
    super.run();
}

private void startServer() {

    try {
        ServerSocket ss = new ServerSocket(8888);
        System.out.println("Esperando Conexion");

        do {
            Socket socket = ss.accept();

            threadPool.execute(new ClientSocket(socket));

        } while(true);

    } catch (IOException ex) {
        Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
    }
}
}

【讨论】:

  • 也就是说,你是什么意思,下面是什么?:public static void main(String[] args) { Client c = new Client("Hilo cliente", 5000, "192.168.0.19"); Client c2 = new Client("Hilo cliente", 5000, "192.168.0.19"); c.start(); c2.start(); }
  • 但是,最好在客户端的 startClient 方法之外获取扫描仪代码,并在连接到服务器之前将标准输入值提供给所有客户端。
  • 如果我理解你的话,最大的问题是我尝试执行时出错,错误在指令中 long tiempo = in.readLong();方法 StartClient (java.net.SocketException: Connection reset)
  • 其实我指的是你读到的代码部分 N (Scannerscanner = new Scanner(System.in); int n =scanner.nextInt();) >> 最好读一下N 仅一次并在构造函数中将其提供给 Client。阅读 tiempo 时是否出现套接字错误?我认为那部分还可以。
  • 是的,虽然每个客户端都可以给出不同的数字,那么这就是为什么我没有将它传递给客户端(Main)的主线程。不,该行在执行时会释放异常,在本例中是客户端的 2 个实例。
猜你喜欢
  • 2015-06-13
  • 2023-01-03
  • 1970-01-01
  • 1970-01-01
  • 2017-02-25
  • 1970-01-01
  • 2017-02-25
  • 2019-09-12
  • 1970-01-01
相关资源
最近更新 更多