简体   繁体   English

如何在Java中通过多个线程发送消息?

[英]How do I send a message over multiple threads in Java?

I made a simple chat server and client and the client will send text to the server, and the server will only send it back to the client that sent it to it. 我做了一个简单的聊天服务器和客户端,客户端将文本发送到服务器,服务器只会将文本发送回发送给它的客户端。 I want it to send to all the clients instead of just that one. 我希望它发送给所有客户端,而不只是发送给所有客户端。

Server: 服务器:

import java.io.IOException;
import java.net.ServerSocket;

public class Server {

    public static void main(String[] args) throws IOException {
        ServerSocket s = null;
        boolean listening = true;
        try {
            s = new ServerSocket(5555);
        } catch (IOException e) {
            e.printStackTrace();
        }

        while(listening)
            new ServerThread(s.accept()).start();

    }

}

Thread: 线:

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

public class ServerThread extends Thread {

    private Socket sock = null;

    public ServerThread(Socket socket) {
        super("Server Thread.");
        this.sock = socket;
    }

    public void run() {

        PrintWriter out = null;
        BufferedReader in = null;

        try {
            System.out.println(sock.getInetAddress() + " has joined.");
            out = new PrintWriter(sock.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(sock.getInputStream()));

            String input;

            while((input = in.readLine()) != null) {
                System.out.println(input);
                out.println(input);
            }

            in.close();
            out.close();
            sock.close();

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

Client: 客户:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client 
{
    public static void main(String[] args) throws IOException {
        Socket sock = null;
        PrintWriter out = null;
        BufferedReader in = null;

        try {
            sock = new Socket("127.0.0.1", 5555);
            out = new PrintWriter(sock.getOutputStream(), true);
            in = new BufferedReader(
                    new InputStreamReader(sock.getInputStream()));
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        BufferedReader stdIn = new BufferedReader(new InputStreamReader(
                System.in));
        String userInput;


        while ((userInput = stdIn.readLine()) != null) {    
            out.println(userInput);
            System.out.println(in.readLine());
        }

        out.close();
        in.close();
        sock.close();
    }

}

Have your server keep List<ServerThread> . 让您的服务器保留List<ServerThread> Have a void sendAll(String) method on the Server that can be accessed by the ServerThreads and when they get information, that sendAll() method tells each ServerThread to send out their information. Server上有一个void sendAll(String)方法, ServerThreads可以访问该ServerThreads ,当它们获取信息时, sendAll()方法告诉每个ServerThread发送其信息。

What you're looking at doing though will require some asynchronous work (and is most certainly not trivial!) 不过,您正在寻找的内容将需要一些异步工作(并且肯定不是一件容易的事!)

Well, briefly: you're creating those ServerThreads and starting them, but you're not keeping track of them in any way. 好吧,简要地说:您正在创建那些ServerThreads并启动它们,但是您并没有以任何方式跟踪它们。 Imagine if each time you created one, you put it in a HashSet. 想象一下,如果每次创建一个,都将其放入HashSet中。 Then each time a client sent a String, you iterated over the Set and sent the String to each of the clients. 然后,每当客户端发送一个String时,您就遍历Set并将String发送给每个客户端。 A method sendMessage(String) in ServerThread would make this easier, of course. 当然,在ServerThread中使用sendMessage(String)方法可以使此操作更加容易。

  1. Change your client to have one thread for reading from the server plus one thread for reading from the keyboard. 更改您的客户端,使其具有一个从服务器读取的线程以及一个从键盘读取的线程。

  2. Create a function which allows server socket threads to communicate with each other and use synchronization so that only one thread is writing to each outputstream at one time. 创建一个函数,该函数允许服务器套接字线程彼此通信并使用同步,以便一次只有一个线程写入每个输出流。 So in brief, create a list of server threads which is shared by all threads and move your PrintWriter into a field with a getter, so it can be accessed from outside. 因此,简而言之,创建一个由所有线程共享的服务器线程列表,然后将PrintWriter移至带有吸气剂的字段中,以便可以从外部进行访问。

glowcoder and Ernest Friedman-Hill seem to be giving good advice, but I wanted to add one thing: have you considered using the Observer pattern and java's default implementation of Observable ? glowcoder和Ernest Friedman-Hill似乎提供了很好的建议,但我想补充一件事:您是否考虑过使用Observer模式和Java的Observable默认实现?

The Server could extend the Observable object, and the ServerThread could implement the Observer interface. 服务器可以扩展Observable对象,而ServerThread可以实现Observer接口。 As you create new ServerThreads, register them with the Observable using 创建新的ServerThreads时,请使用

server.addObserver(serverThread);

The ServerThread will need to know about the Server it is linked to. ServerThread将需要了解链接到的服务器。 Then whenever a client sends in a new message, instead of out.println(userInput) do the following: 然后,每当客户端发送新消息而不是out.println(userInput)时,请执行以下操作:

synchronized (server) {
    server.setChanged();
    server.notifyObservers(userInput);
}

You also need to implement ServerThread.update(Observable o, Object update), in which you would get the serverThread's socket's output stream and write ((String) update) to it. 您还需要实现ServerThread.update(Observable o,Object update),在其中您将获取serverThread的套接字的输出流,并向其写入((String)update)。

Note that this will use one thread to send messages to all the observers and will block other threads from processing their chats until it has sent to all observers. 请注意,这将使用一个线程将消息发送给所有观察者,并且将阻止其他线程处理其聊天,直到将其发送给所有观察者为止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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