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

发布于 2024-10-22 07:25:56 字数 2775 浏览 1 评论 0原文

我做了一个简单的聊天服务器和客户端,客户端将文本发送到服务器,服务器只会将其发送回发送给它的客户端。我希望它发送给所有客户,而不仅仅是那个客户。

服务器:

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

    }

}

线程:

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

    }

}

客户端:

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

}

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

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

眼趣 2024-10-29 07:25:57

Globecoder 和 Ernest Friedman-Hill 似乎提供了很好的建议,但我想补充一件事:您是否考虑过使用观察者模式和 java 的默认实现 可观察

Server可以扩展Observable对象,ServerThread可以实现Observer接口。当您创建新的 ServerThreads 时,使用 Observable 注册它们。

server.addObserver(serverThread);

ServerThread 将需要了解它链接到的服务器。
然后,每当客户端发送新消息时,不要使用 out.println(userInput) 执行以下操作:

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

您还需要实现 ServerThread.update(Observable o, Object update),在其中您将获取 serverThread 的套接字的输出流并写入((字符串)更新)它。

请注意,这将使用一个线程向所有观察者发送消息,并会阻止其他线程处理其聊天,直到消息发送给所有观察者。

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?

The Server could extend the Observable object, and the ServerThread could implement the Observer interface. As you create new ServerThreads, register them with the Observable using

server.addObserver(serverThread);

The ServerThread will need to know about the Server it is linked to.
Then whenever a client sends in a new message, instead of out.println(userInput) do the following:

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.

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.

似狗非友 2024-10-29 07:25:56

让您的服务器保留 List。在 Server 上有一个 void sendAll(String) 方法,该方法可以由 ServerThreads 访问,并且当它们获取信息时,sendAll () 方法告诉每个 ServerThread 发送它们的信息。

不过,您正在做的事情将需要一些异步工作(而且肯定不是微不足道的!)

Have your server keep 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.

What you're looking at doing though will require some asynchronous work (and is most certainly not trivial!)

情感失落者 2024-10-29 07:25:56

好吧,简单地说:您正在创建这些 ServerThreads 并启动它们,但您没有以任何方式跟踪它们。想象一下,如果每次创建一个时,都将其放入 HashSet 中。然后,每次客户端发送字符串时,您都会迭代该集合并将字符串发送给每个客户端。当然,ServerThread 中的方法 sendMessage(String) 会使这变得更容易。

Well, briefly: you're creating those ServerThreads and starting them, but you're not keeping track of them in any way. Imagine if each time you created one, you put it in a HashSet. Then each time a client sent a String, you iterated over the Set and sent the String to each of the clients. A method sendMessage(String) in ServerThread would make this easier, of course.

情域 2024-10-29 07:25:56
  1. 将您的客户端更改为具有 1 个用于从服务器读取的线程和 1 个用于从键盘读取的线程。

  2. 创建一个函数,允许服务器套接字线程相互通信并使用同步,以便一次只有一个线程写入每个输出流。简而言之,创建一个由所有线程共享的服务器线程列表,并将 PrintWriter 移动到带有 getter 的字段中,以便可以从外部访问它。

  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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文