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

Java 从服务器向所有客户端发送消息,java,sockets,networking,client,server,Java,Sockets,Networking,Client,Server,我正在尝试编写一个即时消息系统。。。最初,我是这样做的,一旦我开始工作,我将添加GUI 一旦客户机向服务器发送消息,服务器就应该向所有其他客户机显示该消息。我该怎么做?我一直在尝试一些事情,但它一直只显示给发送消息的客户端 提前谢谢 服务器 import java.io.*; import java.net.*; class Server { //one per server static int port = 3000; private int backlog = 1

我正在尝试编写一个即时消息系统。。。最初,我是这样做的,一旦我开始工作,我将添加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 noob:(

服务器-已更新

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();
    }
}
包csci2020\u分配51;
导入java.io.*;
导入java.net。*;
导入java.util.ArrayList;
导入java.util.Collections;
导入java.util.List;
类服务器{
//每台服务器一个
静态int端口=3000;
私人int积压=100;
服务器插座主;
静态数据输出流数据输出;
静态数据输入流数据输入;
静态字符串扫描消息;
静态列表mailServers=Collections.synchronizedList(新的ArrayList());
静态BufferedReader br=新的BufferedReader(新的InputStreamReader(System.in));
静态类MailServer扩展线程{
//每个客户一个
静态整数指数;
字符串名称=Client.name;
公共邮件服务器(int索引、DataInputStream输入、DataOutputStream输出){
Server.dataIn=in;
Server.dataOut=out;
this.index=index;//线程索引,每个客户端一个
}
public void run(){
while(true){
试一试{
字符串receivedMessage=dataIn.readUTF();
String outputMessage=“Client”+index+”表示:“+receivedMessage;
//将receivedMessage打印到所有客户端
用于(邮件服务器邮件服务器:邮件服务器){
dataOut.writeUTF(outputMessage);
}
}捕获(例外e){
打破
}
}
}
}
公共服务器(int端口)引发异常{
this.main=新服务器套接字(端口);
}
//发球
public void service()引发异常{
int指数=1;
while(true){
套接字=this.main.accept();
InputStream in=socket.getInputStream();
OutputStream out=socket.getOutputStream();
DataInputStream dataIn=新的DataInputStream(in);
DataOutputStream dataOut=新的DataOutputStream(输出);
//处理连接
//使用infinite循环继续阅读
System.out.println(“处理与客户端的连接”+索引+”);
MailServer MailServer=新的MailServer(索引、数据输入、数据输出);
mailServer.start();
添加(mailServer);
dataOut.writeUTF(“客户机”+索引);
index+=1;//每次添加新客户端时添加一个
}
}
公共静态void main(字符串[]args)引发异常{
服务器s=新服务器(端口);
System.out.println(“服务…”);
s、 发球();
}
}

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

 static List<MailServer> servers=Collections.<MailServer>synchronizedList(new LinkedList<MailServer>);
 ...
 MailServer s=new MailServer(index, dataIn, dataOut);
 servers.add(s);
 s.start();
您的通知循环将变为:

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

我也不明白您希望如何在服务器中获取Client.name,因为Client在另一台机器上运行……现在就把它去掉。

我应该把那部分代码放在哪里?我尝试在不同的地方添加它,但我不断地出错:(好的,您将服务器添加到列表中,在serve方法中创建它们…您在Server类中定义的列表。。。
 for(MailServer mailServer:mailServers){
   if (mailServer!=this){
    mailServer.dataOut.writeUtf(...);
   }
 }