java中的多客户端聊天应用
我刚刚开始使用socket编程,所以为了提高我对它的理解,我想构建一个多客户端聊天应用程序 我打算这样做的方式如下: 应用程序启动后,您有两个选择:创建服务器或加入服务器 如果您选择创建一个服务器,一个新线程将启动并托管服务器,然后另一个线程将启动,它将创建一个新的客户端并自动连接到服务器 在这里我遇到了以下问题。 每个客户端都可以向服务器发送消息,但为了使所有客户端的消息保持同步,我想将检索到的消息从服务器重定向到所有客户端,如下图所示。 问题是,当我尝试在客户机和服务器上侦听和发送时,我会遇到这样的错误java中的多客户端聊天应用,java,sockets,client-server,chat,serversocket,Java,Sockets,Client Server,Chat,Serversocket,我刚刚开始使用socket编程,所以为了提高我对它的理解,我想构建一个多客户端聊天应用程序 我打算这样做的方式如下: 应用程序启动后,您有两个选择:创建服务器或加入服务器 如果您选择创建一个服务器,一个新线程将启动并托管服务器,然后另一个线程将启动,它将创建一个新的客户端并自动连接到服务器 在这里我遇到了以下问题。 每个客户端都可以向服务器发送消息,但为了使所有客户端的消息保持同步,我想将检索到的消息从服务器重定向到所有客户端,如下图所示。 问题是,当我尝试在客户机和服务器上侦听和发送时,我会
java.net.SocketException: Connection reset
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:186)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:200)
at java.base/java.io.DataInputStream.readUnsignedShort(DataInputStream.java:342)
at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:594)
at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:569)
at parctice.Server.lambda$main$0(Server.java:32)
at java.base/java.lang.Thread.run(Thread.java:835)
这是我的服务器:
int port = 4444;
try {
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("server starts port = " + serverSocket.getLocalSocketAddress());
while(true){
Socket socket = serverSocket.accept();
System.out.println("accepts : " + socket.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
String[] message = {""};
new Thread(() -> {
try {
while(in.available() > 0){
System.out.println("SERVER > " + in.readUTF());
message[0] = in.readUTF();
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
System.err.println(message[0]);
try {
out.writeUTF(message[0] + "REDIRECTED MESSAGE");
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
我的客户:
int portNumber = 4444;
System.out.println("CLIENT > Trying to connect to the server...");
try {
Socket socket = new Socket("localhost", portNumber);
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
new Thread(() -> {
try {
while(in.available() > 0){
System.out.println("SERVER > " + in.readUTF());
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
try {
out.writeUTF("test");
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
最后,我想问你们,你们是否认为我尝试使用的逻辑是正确的,如果不是,请让我知道是什么错了,如果可能的话,你们能解释一下为什么我不能同时在客户端和服务器上进行监听和发送吗?因为当我尝试通过客户端发送数据并在服务器上检索数据时,它工作得很好,但我希望实现双向通信 我发现这个解决方案似乎适用于这种情况 第一次创建服务器时:
private List<ClientThread> clients; // or "protected static List<ClientThread> clients;"
public List<ClientThread> getClients(){
return clients;
}
private void startServer(){
clients = new ArrayList<ClientThread>();
try {
serverSocket = new ServerSocket(PORT);
System.out.println("SERVER ON");
System.out.println("SERVER > Waiting for connections...");
// ACCEPT ALL CONNECTIONS
while (true){
try {
Socket socket = serverSocket.accept();
System.out.println("SERVER > New connection: " + socket.getRemoteSocketAddress());
ClientThread client = new ClientThread(this, socket);
Thread thread = new Thread(client);
thread.start();
clients.add(client);
} catch (IOException e) {
e.printStackTrace();
System.out.println("SERVER > Accept failed");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
客户:
public void createClient(){
try {
socket = new Socket("localhost", portNumber);
// socket = new Socket(getHost(), portNumber);
DataInputStream in = new DataInputStream(socket.getInputStream());
new Thread(()->{
while(!socket.isClosed()){
try {
if (in.available() > 0){
String input = in.readUTF();
System.out.println(getUserName() + " > " + input);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
你能举一个完整输出的例子吗?
System.out.println(“SERVER>”+in.readUTF());消息[0]=in.readUTF()
实际上尝试从套接字读取两个UTF字符串。除了抛出异常,您也无法检测客户端何时关闭了连接。客户端几乎在写入“test”后立即关闭连接。在大多数情况下,使用.available()
是错误的。
public void createClient(){
try {
socket = new Socket("localhost", portNumber);
// socket = new Socket(getHost(), portNumber);
DataInputStream in = new DataInputStream(socket.getInputStream());
new Thread(()->{
while(!socket.isClosed()){
try {
if (in.available() > 0){
String input = in.readUTF();
System.out.println(getUserName() + " > " + input);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}