处理多个客户端的流?

时间:2012-08-13 00:02:51

标签: java sockets stream

基本上我想要做的是开发一个聊天程序(即时通讯工具和IRC之间的东西)来提高我的java技能。

但到目前为止我遇到了一个大问题:如果有多个客户端,我不知道如何正确设置流。客户端和服务器之间的1:1聊天工作很容易,但我只是不知道什么是todo,所以超过1个客户端可以在同一个聊天中使用服务器。

这就是我所得到的,但我怀疑它会非常有用,因为它只是来自服务器的1个永久流。

private void connect() throws IOException {
        showMessage("Trying to connect \n");
        connection = new Socket(InetAddress.getByName(serverIP),27499);
        showMessage("connected to "+connection.getInetAddress().getHostName());

    }

    private void streams() throws IOException{
        output = new ObjectOutputStream(connection.getOutputStream());
        output.flush();
        input = new ObjectInputStream(connection.getInputStream());
        showMessage("\n streams working");

    }

3 个答案:

答案 0 :(得分:0)

要从一个程序中的多个流中读取,您将不得不使用多线程。因为从流中读取是同步的,所以您需要从每个线程的一个流中读取。有关多线程的详细信息,请参阅java tutorial on threads

答案 1 :(得分:0)

几个月前做了类似的东西。基本上我每个客户端服务器端使用一个单独的ServerSocketThread。当客户端连接时,您将该端口的输入和输出流注册到固定池并阻塞,直到发送输入。然后将输入复制到每个其他客户端并发送。这是从命令行运行的基本程序:    服务器代码:

    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.ArrayList;

    public class ChatServer {

        static int PORT_NUMBER = 2012;

        public static void main(String[] args) throws IOException {


            while (true) {
                try (ServerSocket ss = new ServerSocket(PORT_NUMBER)) {
                    System.out.println("Server waiting @" + ss.getInetAddress());
                    Socket s = ss.accept();
                    System.out.println("connection from:" + s.getInetAddress());

                    new Worker(s).start();
                }
            }

        }

        static class Worker extends Thread {

            final static  ArrayList<PrintStream> os = new ArrayList(10);
            Socket clientSocket;
            BufferedReader fromClient;

            public Worker(Socket clientSocket) throws IOException {
                this.clientSocket = clientSocket;
                PrintStream toClient=new PrintStream(new BufferedOutputStream(this.clientSocket.getOutputStream()));
                toClient.println("connected to server");
                os.add(toClient);
                fromClient = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));

            }
            @Override
            public void run() {

                while (true) {
                    try {
                        String message = fromClient.readLine();
                        synchronized (os) {


                            for (PrintStream toClient : os) {
                                toClient.println(message);
                                toClient.flush();
                            }
                        }

                    } catch (IOException ex) {
                        //user discnnected
                        try {
                            clientSocket.close();
                        } catch (IOException ex1) {

                        }
                    }

                }
            }
        }

}

客户代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

public class Client {

    public static void main(String[] args) throws IOException {

        final BufferedReader fromUser = new BufferedReader(new InputStreamReader(System.in));
        PrintStream toUser = System.out;
        BufferedReader fromServer;
        final PrintStream toServer;
        Socket s = null;

        System.out.println("Server IP Address?");


        String host;
        String port = "";


        host = fromUser.readLine();

        System.out.println("Server Port Number?");

        port = fromUser.readLine();

        s = new Socket(host, Integer.valueOf(port));

        int read;
        char[] buffer = new char[1024];


        fromServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
        toServer = new PrintStream(s.getOutputStream());
        new Thread() {

            @Override
            public void run() {
                while (true) {
                    try {
                        toServer.println(">>>" + fromUser.readLine());

                        toServer.flush();
                    } catch (IOException ex) {
                        System.err.println(ex);
                    }
                }
            }
        }.start();
        while (true) {
            while ((read = fromServer.read(buffer)) != -1) {
                toUser.print(String.valueOf(buffer, 0, read));
            }
            toUser.flush();

        }
    }
}

答案 2 :(得分:0)

我已使用ServerSocket(int port)Socket ServerSocket.accept()多次完成此操作。通过让它监听您希望聊天服务器客户端监听的一个端口,这可以非常简单。主线程将阻止等待下一个客户端连接,然后将Socket对象返回到该特定客户端。通常,您会希望将它们放在一个列表中,以便一般地处理n个客户端。

而且,是的,您可能希望确保每个Socket位于不同的主题中,但这完全取决于您作为程序员。

请记住,由于客户端使用不同的源端口,独特的5元组(SrcIP,SrcPort,DstIP,DstPort,TCP / UDP /其他),因此无需重定向到服务器上的其他端口IP协议)将允许重用一个服务器端口。因此,为什么我们都使用stackoverflow.com端口80。

快乐编码。