如何在 Java 中通过多个线程发送消息?
我做了一个简单的聊天服务器和客户端,客户端将文本发送到服务器,服务器只会将其发送回发送给它的客户端。我希望它发送给所有客户,而不仅仅是那个客户。
服务器:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Globecoder 和 Ernest Friedman-Hill 似乎提供了很好的建议,但我想补充一件事:您是否考虑过使用观察者模式和 java 的默认实现 可观察?
Server可以扩展Observable对象,ServerThread可以实现Observer接口。当您创建新的 ServerThreads 时,使用 Observable 注册它们。
ServerThread 将需要了解它链接到的服务器。
然后,每当客户端发送新消息时,不要使用 out.println(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
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:
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.
让您的服务器保留
List
。在Server
上有一个void sendAll(String)
方法,该方法可以由ServerThreads
访问,并且当它们获取信息时,sendAll ()
方法告诉每个ServerThread
发送它们的信息。不过,您正在做的事情将需要一些异步工作(而且肯定不是微不足道的!)
Have your server keep
List<ServerThread>
. Have avoid sendAll(String)
method on theServer
that can be accessed by theServerThreads
and when they get information, thatsendAll()
method tells eachServerThread
to send out their information.What you're looking at doing though will require some asynchronous work (and is most certainly not trivial!)
好吧,简单地说:您正在创建这些 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.
将您的客户端更改为具有 1 个用于从服务器读取的线程和 1 个用于从键盘读取的线程。
创建一个函数,允许服务器套接字线程相互通信并使用同步,以便一次只有一个线程写入每个输出流。简而言之,创建一个由所有线程共享的服务器线程列表,并将 PrintWriter 移动到带有 getter 的字段中,以便可以从外部访问它。
Change your client to have one thread for reading from the server plus one thread for reading from the keyboard.
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.