从服务器向所有客户端发送消息

时间:2015-04-14 19:36:49

标签: java sockets networking client server

我正在尝试对即时消息系统进行编码......最初,我是这样做的,一旦我开始工作,我就会添加GUI。

一旦客户端向服务器发送消息,服务器就应该将其显示给所有其他客户端。我怎样才能做到这一点?我一直在尝试一些东西,但它一直只显示给发送消息的客户端......

提前致谢!

服务器

import java.io.*;
import java.net.*;

class Server {
    //one per server
    static int port = 3000;
    private int backlog = 100;
    ServerSocket main;
    static DataOutputStream dataOut;
    static DataInputStream dataIn;
    static String scannerMessage;

    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    static class MailServer extends Thread {
        //one per client
        static int index;
        String name = Client.name;

        public MailServer(int index, DataInputStream in, DataOutputStream out) {
            Server.dataIn = in;
            Server.dataOut = out;
            this.index = index; // thread index, one per client
        }

        public void run() {
            while (true) {
                try {
                    String receivedMessage = dataIn.readUTF();

                    //print receivedMessage to all clients

                } catch (Exception e) {
                    break;
                }
            }
        }
    }


    public Server(int port) throws Exception {
        this.main = new ServerSocket(port);
    }

    // start a serve
    public void serve() throws Exception {
        int index = 1;
        while (true) {
            Socket socket = this.main.accept();
            InputStream in = socket.getInputStream();
            OutputStream out = socket.getOutputStream();
            DataInputStream dataIn = new DataInputStream(in);
            DataOutputStream dataOut = new DataOutputStream(out);

            // handle the connection
            // keep reading using an infintite loop
            System.out.println("Handling connection to Client " + index + "...");
            (new MailServer(index, dataIn, dataOut)).start();
            index += 1; // add one every time a new client is added
        }
    }

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

        Server s = new Server(port);
        System.out.println("Serving....");
        s.serve();
    }
}

客户端

import java.io.*;
import java.net.*;

class Client {

    static String hostname = "127.0.0.1";
    static int port = Server.port;
    static Socket socket;
    static String name;

    static class Sender extends Thread {
        DataOutputStream dataOut;
        public Sender(DataOutputStream dataOut) {
            this.dataOut = dataOut;
        }
        public void run() {
            while(true) {
                //get a message from the user
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
                try {
                    String message = br.readLine();
                    dataOut.writeUTF(message);
                    dataOut.flush();
                } catch(Exception e) {
                    break;
                }
            }
        }
    }

    static class Receiver extends Thread {
        DataInputStream dataIn;
        public Receiver(DataInputStream dataIn) {
            this.dataIn = dataIn;
        }
        public void run() {
            while(true) {
                try {
                    //RECEIVE A MESAGE FROM THE SERVER (ending in \n)
                    String msg = dataIn.readUTF();
                    while (msg != null) {
                        System.out.println(msg);
                        msg = dataIn.readUTF();
                    }
                } catch(Exception e) {
                    break;
                }
            }
        }
    }

    //client will require host name and the port
    public Client(String hostname, int port) throws Exception {
        socket = new Socket(hostname, port);
    }

    public void connect() throws Exception {
        InputStream in = socket.getInputStream();
        OutputStream out = socket.getOutputStream();
        DataInputStream dataIn = new DataInputStream(in);
        DataOutputStream dataOut = new DataOutputStream(out);

        //handle the connection
        System.out.println("Handling connection to server...");
        Thread sender = new Sender(dataOut);
        Thread receiver = new Receiver(dataIn);

        sender.start();
        receiver.start();

        sender.join();
        receiver.join();

        System.out.println("Client " + Server.MailServer.index);
        System.out.println("----------------------");
    }

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

            Client c = new Client(hostname, port);
            c.connect();
        }
}

更新:我创建了一个包含所有MailServer对象的列表,然后通过它们迭代将消息发送给所有客户端,正如JP Moresmau建议的那样......但现在第一个发送内容的客户端收到所有输出。为什么是这样?我该怎么解决它?谢谢,对不起,如果我的问题看起来太明显或愚蠢,我还是一个Java菜鸟:(

服务器 - 更新

package csci2020_assignment51;

import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


class Server {
    //one per server
    static int port = 3000;
    private int backlog = 100;
    ServerSocket main;
    static DataOutputStream dataOut;
    static DataInputStream dataIn;
    static String scannerMessage;

    static List<MailServer> mailServers = Collections.<MailServer>synchronizedList(new ArrayList<MailServer>());


    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    static class MailServer extends Thread {
        //one per client
        static int index;
        String name = Client.name;

        public MailServer(int index, DataInputStream in, DataOutputStream out) {        
            Server.dataIn = in;
            Server.dataOut = out;
            this.index = index; // thread index, one per client

        }

        public void run() { 
            while (true) {
                try {
                    String receivedMessage = dataIn.readUTF();
                    String outputMessage = "Client " + index + " said: " + receivedMessage;

                    //print receivedMessage to all clients
                    for (MailServer mailserver : mailServers) {
                        dataOut.writeUTF(outputMessage);
                    }

                } catch (Exception e) {
                    break;
                }
            }
        }
    }


    public Server(int port) throws Exception {
        this.main = new ServerSocket(port);
    }

    // start a serve
    public void serve() throws Exception {
        int index = 1;
        while (true) {
            Socket socket = this.main.accept();
            InputStream in = socket.getInputStream();
            OutputStream out = socket.getOutputStream();
            DataInputStream dataIn = new DataInputStream(in);
            DataOutputStream dataOut = new DataOutputStream(out);

            // handle the connection
            // keep reading using an infintite loop
            System.out.println("Handling connection to Client " + index + "...");
            MailServer mailServer = new MailServer(index, dataIn, dataOut);
            mailServer.start();
            mailServers.add(mailServer);
            dataOut.writeUTF("Client " + index);
            index += 1; // add one every time a new client is added
        }
    }

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

        Server s = new Server(port);
        System.out.println("Serving....");
        s.serve();
    }
}

1 个答案:

答案 0 :(得分:2)

拥有您创建的所有MailServer对象的静态列表

 static List<MailServer> servers=Collections.<MailServer>synchronizedList(new LinkedList<MailServer>);
 ...
 MailServer s=new MailServer(index, dataIn, dataOut);
 servers.add(s);
 s.start();

然后当其中一个收到消息时,循环遍历它们,并且对于所有人都期望接收者,将消息写入其输出。

代码中的一个大问题是dataOut和dataIn是唯一的!您需要将它们移动到MailServer类。每个MailServer与一个特定的客户端进行通信,因此需要拥有自己的流。

static class MailServer extends Thread {
    DataOutputStream dataOut;
    DataInputStream dataIn;

您的通知循环变为:

 for(MailServer mailServer:mailServers){
   if (mailServer!=this){
    mailServer.dataOut.writeUtf(...);
   }
 }

我也不明白你希望如何在服务器中获取Client.name,因为客户端在另一台机器上运行...暂时摆脱它。