gpt4 book ai didi

java - 如何通过所有线程发送消息?

转载 作者:行者123 更新时间:2023-12-01 19:31:55 24 4
gpt4 key购买 nike

目前我有一个服务器和一个客户端,当客户端连接到服务器时,会创建一个线程来处理来自各个客户端的所有响应,并发送任何需要的答案。我现在的问题是我需要能够通过每个现有线程向各自的客户端发送消息。

我想这样做:

public class ServerThread extends Thread {
//ignore most of the constructor, just things i need
public ServerThread(Socket socket, int threadId, Manager manager) throws Exception {
try {
this.socket = socket;
this.threadId=threadId;
this.manager=manager;
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
manager.addThread(); //This should add this Thread to the Collection in the Manager class
} catch (IOException ex) {
throw new Exception("Error", ex);
}
}


public void notify(String message){
// Do something
}

//In the end of the thread i would call manager.removeThread to remove the Thread from the Collection

}

public class Manager {

private //Thread Collection here

public Manager(){
//Initialize the collection;
}

public void addThread(){
//Add thread
}

public void removeThread(){
//Remove Thread
}
}

如果这是处理此问题的可行选项,我需要什么集合来存储线程,以及 notify(String message) 方法是什么样的?它需要调用 Manager 中的一个方法来向每个线程发送消息,对吧?

最佳答案

如果你想创建一个多客户端服务器,通常建议在服务器类的主线程(或单独的线程)中,服务器将接受传入的套接字(客户端),并且每个套接字接受一个创建新线程来为该客户端提供服务,最好将该服务作为实现可运行或扩展线程的单独类。 每个服务线程都将等待与其关联的客户端的输入,并根据客户端的请求进行回复。

如果您希望向所有连接的客户端广播数据,那么您需要一个 ArrayList 来存储客户端服务对象,然后循环遍历它,每次循环发送数据时已连接的客户端之一,但您必须确保删除与 ArrayList 断开连接的客户端,否则它将开始引发异常。

通常,客户端服务类具有接受的套接字、输入流和输出流。

这是我制作的多客户端回显服务器的示例,也许它会有所帮助。

public class TcpServer {

public TcpServer(){
ServerSocket server = null;
try{
server = new ServerSocket(9991);
while(!server.isClosed()){
Socket acceptedSocket = server.accept();
EchoService service = new EchoService(acceptedSocket);
service.start();

}
}catch (IOException e){
e.printStackTrace();
} finally {
if(server!=null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args){
new TcpServer();
}}

这是服务类:

public class EchoService extends Thread {
private Socket acceptedSocket;
private DataInputStream is;
private DataOutputStream os;

public EchoService(Socket acceptedSocket) {
try {
this.acceptedSocket = acceptedSocket;
is = new DataInputStream(acceptedSocket.getInputStream());
os = new DataOutputStream(acceptedSocket.getOutputStream());
} catch (IOException e) {
try {
if (this.acceptedSocket != null)
acceptedSocket.close();
if(is != null)
is.close();
if(os != null)
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}


@Override
public void run() {
super.run();
try {
while (!acceptedSocket.isClosed()) {
String usrMsg = is.readUTF();
String serverMsg = "server: "+usrMsg;
os.writeUTF(serverMsg);
os.flush();
}
} catch (IOException e) {
try {
if(this.acceptedSocket != null)
acceptedSocket.close();
if(is != null)
is.close();
if(os != null)
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}}

这是同一示例,但包含广播功能

服务器类别:

package TCP;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class TcpServer {
public static ArrayList<EchoService> connectedServices;

public TcpServer(){
ServerSocket server = null;
try{
server = new ServerSocket(9991);
System.out.println("server started");
connectedServices = new ArrayList<>();
while(!server.isClosed()){
Socket acceptedSocket = server.accept();
System.out.println("client connected: "
+acceptedSocket.getInetAddress());
EchoService service = new EchoService(acceptedSocket);
service.start();

}
}catch (IOException e){
e.printStackTrace();
} finally {
if(server!=null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args){
new TcpServer();
}

public static void removeConnectedService(EchoService client) {
boolean removed = connectedServices.remove(client);
System.out.println("client has been removed"+
client.getAcceptedSocket().getInetAddress()+", "+removed);
}

public static void broadCastMsg(long id, String usrMsg) throws IOException {
for(EchoService client: connectedServices){
if(client.getId()!=id)
{
String serverMsg = "server broadcast: " + usrMsg;
client.getOs().writeUTF(serverMsg);
client.getOs().flush();
}
}

}
}

服务等级:

    package TCP;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class EchoService extends Thread {
private Socket acceptedSocket;
private DataInputStream is;
private DataOutputStream os;

public EchoService(Socket acceptedSocket) {
try {
this.acceptedSocket = acceptedSocket;
is = new DataInputStream(acceptedSocket.getInputStream());
os = new DataOutputStream(acceptedSocket.getOutputStream());

} catch (IOException e) {
try {
if (this.acceptedSocket != null)
acceptedSocket.close();
if(is != null)
is.close();
if(os != null)
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}


@Override
public void run() {
super.run();
try {
TcpServer.connectedServices.add(this);
while (!acceptedSocket.isClosed()) {
String usrMsg = is.readUTF();
if(usrMsg.contains("BROADCAST"))
TcpServer.broadCastMsg(this.getId(),usrMsg);
else {
String serverMsg = "server: " + usrMsg;
os.writeUTF(serverMsg);
os.flush();
}
}
} catch (IOException e) {
TcpServer.removeConnectedService(this);
try {
if(this.acceptedSocket != null)
acceptedSocket.close();
if(is != null)
is.close();
if(os != null)
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}

public DataInputStream getIs() {
return is;
}

public DataOutputStream getOs() {
return os;
}

public Socket getAcceptedSocket() {
return acceptedSocket;
}
}

服务器输出:

enter image description here

客户端1输出:

enter image description here

客户端2输出:

enter image description here

客户端3输出:

enter image description here

关于java - 如何通过所有线程发送消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59492384/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com