简体   繁体   中英

Handle streams with multiple clients?

basically what i want to do is develop a chat program(something between an instant messenger and IRC) to improve my java skills.

But I ran into 1 big problem so far: I have no idea how to set up streams properly if there is more than one client. 1:1 chat between the client and the server works easily, but I just don't know what todo so more than 1 client can be with the server in the same chat.

This is what I got, but I doubt its going to be very helpful, since it is just 1 permanent stream to and from the server.

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");

    }

To read from multiple streams in one program, you're going to have to use multithreading. Because reading from streams is synchronous, you'll need to read from one stream for each thread. See the java tutorial on threads for more info on multithreading.

Made something like that a few months back. basically I used a separate ServerSocket and Thread per client server side. When client connects you register that port's input and output streams to a fixed pool and block until input is sent. then you copy the input to each of the other clients and send. here is a basic program run from command line: Server code:

    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) {

                        }
                    }

                }
            }
        }

}

Client code:

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();

        }
    }
}

I've done this several times with ServerSocket(int port) and Socket ServerSocket.accept() . This can be pretty simple by having it listen to the one port you want your chat server client listening on. The main thread will block waiting for the next client to connect, then return the Socket object to that specific client. Usually you'll want to put them in a list to generically handle n-number of clients.

And, yes, you will probably want to make sure each Socket is in a different thread, but that's entirely up to you as the programmer.

Remember, there is no need to re-direct to another port on the server, by virtue of the client using a different source port, the unique 5-tuple (SrcIP, SrcPort, DstIP, DstPort, TCP/UDP/other IP protocol) will allow the one server port to be re-used. Hence why we all use stackoverflow.com port 80.

Happy Coding.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM