Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何创建接受客户端连接的java服务器,然后为客户端对构建中继连接_Java_Multithreading_Sockets - Fatal编程技术网

如何创建接受客户端连接的java服务器,然后为客户端对构建中继连接

如何创建接受客户端连接的java服务器,然后为客户端对构建中继连接,java,multithreading,sockets,Java,Multithreading,Sockets,我想创建一个可以接受多个连接的服务器,然后将两个客户端成对绑定,并在这两个客户端之间转发数据。但它涉及多对客户机。我已经有了多线程服务器,可以为每个新连接的客户端创建一个新线程。我的问题是,这些线程彼此不认识,我不得不将两个客户端连接到一个连接对 现在,我只是这样创建这些对连接:我等待第一个客户机,然后等待第二个客户机,然后打开一个线程,用于将客户机1的输入转发到客户机2,反之亦然。这不适用于多个客户端 我怎样才能做到这一点呢?在我看来,客户需要 与服务器建立TCP连接, 自认 提供希望与之交谈

我想创建一个可以接受多个连接的服务器,然后将两个客户端成对绑定,并在这两个客户端之间转发数据。但它涉及多对客户机。我已经有了多线程服务器,可以为每个新连接的客户端创建一个新线程。我的问题是,这些线程彼此不认识,我不得不将两个客户端连接到一个连接对

现在,我只是这样创建这些对连接:我等待第一个客户机,然后等待第二个客户机,然后打开一个线程,用于将客户机1的输入转发到客户机2,反之亦然。这不适用于多个客户端


我怎样才能做到这一点呢?

在我看来,客户需要

与服务器建立TCP连接, 自认 提供希望与之交谈的其他客户的ID 在第二个客户端连接之前,第一个连接的客户端必须保持在服务器中某个全局表中。 一旦一对客户端被识别为对话者,您将创建一对线程,将每个客户端发送的数据转发给另一个客户端

更新:示例

ClientSocket.java

package matchmaker;

import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class ClientSocket implements Closeable {
    private final Socket socket;
    private final InputStream in;
    private final OutputStream out;
    private final String ownId;
    private final String peerId;

    public ClientSocket(Socket socket) throws IOException {
        this.socket = socket;
        this.in = socket.getInputStream();
        this.out = socket.getOutputStream();
        DataInputStream din = new DataInputStream(in);
        this.ownId = din.readUTF();
        this.peerId = din.readUTF();
    }

    public ClientSocket(String server, int port, String ownId, String peerId)
            throws IOException {
        this.socket = new Socket(server, port);
        this.socket.setTcpNoDelay(true);
        this.in = socket.getInputStream();
        this.out = socket.getOutputStream();
        this.ownId = ownId;
        this.peerId = peerId;
        DataOutputStream dout = new DataOutputStream(out);
        dout.writeUTF(ownId);
        dout.writeUTF(peerId);
    }

    public String getOwnId() {
        return ownId;
    }

    public String getPeerId() {
        return peerId;
    }

    public InputStream getInputStream() {
        return in;
    }

    public OutputStream getOutputStream() {
        return out;
    }

    @Override
    public void close() throws IOException {
        socket.close();
    }
}
java:服务器

package matchmaker;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Matchmaker extends Thread {
    private static final Logger LOG
            = Logger.getLogger(Matchmaker.class.getName());

    private final int port;
    private final Map<ClientPair,ClientSocket> waiting = new HashMap<>();

    public static void main(String[] args) {
        try {
            int port = 1234;
            int st = 0;
            for (String arg: args) {
                switch (st) {
                    case 0:
                        switch (arg) {
                            case "-p":
                                st = 1;
                                break;
                            default:
                                System.out.println("Unknown option: " + arg);
                                return;
                        }
                        break;
                    case 1:
                        port = Integer.parseInt(arg);
                        st = 0;
                        break;
                }
            }
            Matchmaker server = new Matchmaker(port);
            server.start();
            server.join();
        } catch (InterruptedException ex) {
            LOG.log(Level.SEVERE, null, ex);
        }
    }

    private Matchmaker(int port) {
        this.port = port;
        setDaemon(true);
    }

    @Override
    public void run() {
        try {
            ServerSocket server = new ServerSocket(port);
            while (true) {
                ClientSocket socket = new ClientSocket(server.accept());
                ClientPair pair = new ClientPair(
                        socket.getOwnId(), socket.getPeerId());
                ClientSocket other;
                synchronized(this) {
                    other = waiting.remove(pair.opposite());
                    if (other == null) {
                        waiting.put(pair, socket);
                    }
                }
                if (other != null) {
                    LOG.log(Level.INFO, "Establishing connection for {0}",
                            pair);
                    establishConnection(socket, other);
                } else {
                    LOG.log(Level.INFO, "Waiting for counterpart {0}", pair);
                }
            }
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, null, ex);
        }
    }

    private void establishConnection(ClientSocket socket, ClientSocket other)
            throws IOException {
        Thread thread = new StreamCopier(
                socket.getInputStream(), other.getOutputStream());
        thread.start();
        thread = new StreamCopier(
                other.getInputStream(), socket.getOutputStream());
        thread.start();
    }
}
java:一对客户端ID

package matchmaker;

public class ClientPair {
    private final String client1;
    private final String client2;

    public ClientPair(String client1, String client2) {
        this.client1 = client1;
        this.client2 = client2;
    }

    public String getClient1() {
        return client1;
    }

    public String getClient2() {
        return client2;
    }

    public ClientPair opposite() {
        return new ClientPair(client2, client1);
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 73 * hash + client1.hashCode();
        hash = 73 * hash + client2.hashCode();
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final ClientPair other = (ClientPair) obj;
        return client1.equals(other.client1) && client2.equals(other.client2);
    }

    @Override
    public String toString() {
        return "[" + client1 + "," + client2 + "]";
    }
}
java:从套接字读取数据并写入标准输出的示例客户端

package matchmaker;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ReaderClient {
    private static final Logger LOG = Logger.getLogger(ReaderClient.class.getName());

    public static void main(String[] args) {
        try (ClientSocket client
                = new ClientSocket("localhost", 1234, "reader", "writer")) {
            Reader reader
                    = new InputStreamReader(client.getInputStream(), "UTF-8");
            BufferedReader in = new BufferedReader(reader);
            for (String s = in.readLine(); s != null; s = in.readLine()) {
                System.out.println(s);
            }
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, null, ex);
        }
    }
}
WriterClient.java:写入套接字的示例客户端

package matchmaker;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.logging.Level;
import java.util.logging.Logger;

public class WriterClient {
    private static final Logger LOG = Logger.getLogger(ReaderClient.class.getName());

    public static void main(String[] args) {
        try (ClientSocket client
                = new ClientSocket("localhost", 1234, "writer", "reader")) {
            Writer writer
                    = new OutputStreamWriter(client.getOutputStream(), "UTF-8");
            PrintWriter out = new PrintWriter(writer);
            for (int i = 0; i < 30; ++i) {
                out.println("Message line " + i);
            }
            out.flush();
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, null, ex);
        }
    }    
}

我猜您必须以某种方式识别每个客户端,不是吗?是的,我知道要连接哪个客户端对,因为它们在连接到服务器后必须发送唯一的ID。我的问题是,如果我为每个客户机打开一个线程并等待输入流,如何连接在不同线程中处理的这两个客户机?我的问题是。如果第一个连接的客户机在一个新线程中被标识,而另一个客户机随后也在另一个线程中被标识。我如何连接这两个?也许我会创建另一个线程来查找一个数组,其中每个套接字及其id在它们连接后都会保存,然后将两个客户端作为单独的线程连接起来?在双方联机之前,您不需要创建任何线程。服务器线程池除外。在任何情况下,都需要一个得到充分保护的全局表来进行匹配。
package matchmaker;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.logging.Level;
import java.util.logging.Logger;

public class WriterClient {
    private static final Logger LOG = Logger.getLogger(ReaderClient.class.getName());

    public static void main(String[] args) {
        try (ClientSocket client
                = new ClientSocket("localhost", 1234, "writer", "reader")) {
            Writer writer
                    = new OutputStreamWriter(client.getOutputStream(), "UTF-8");
            PrintWriter out = new PrintWriter(writer);
            for (int i = 0; i < 30; ++i) {
                out.println("Message line " + i);
            }
            out.flush();
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, null, ex);
        }
    }    
}