java 服务器在新客户端加入时放弃旧客户端
java server gives up on older clients whenever a new one joins
首先我想介绍一下我现在的代码:
/**
App.java:
**/
package org.example;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class App
{
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(2343);
} catch (IOException e) {
System.err.println("Could not listen on 2343");
}
try {
while (true) {
Socket clientSocket = serverSocket.accept();
try {
new Helper(clientSocket);
} catch (IOException e) {
clientSocket.close();
}
}
} finally {
serverSocket.close();
}
}
}
/**
Helper.java:
**/
package org.example;
import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class Helper extends Thread {
public static BufferedReader br;
public static BufferedWriter bw;
public static String output = "";
public Helper(Socket socket) throws IOException {
System.out.println("user found");
br = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8));
start();
}
@Override
public void run() {
while (true) {
try {
bw.write("set");
bw.newLine();
bw.flush();
System.out.println(br.readLine()+"\n"+getId());
} catch (IOException e) {
System.out.println("Client Lost");
break;
}
}
}
}
/**
Cli.java
**/
package org.example2;
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
class Cli {
public static void main(String[] argv) throws Exception {
BufferedWriter bw;
Socket clientSocket;
BufferedReader br;
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
clientSocket = new Socket("laith.com.au", 2343);
bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream(), StandardCharsets.UTF_8));
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), StandardCharsets.UTF_8));
while(true){
String input=br.readLine();
bw.write(inFromUser.readLine());
bw.newLine();
bw.flush();
}
}
}
其次我将展示输出:
App.java
user found
hello world
13
hello world
13
user found
hello world
14
hello world
14
hello world
13
Client Lost
Client Lost
Cli.java(no1 所有用户输入)
hello world
hello world
hello world
hello world
Cli.java(no2 所有用户输入)
hello world
hello world
成绩单:
我启动应用程序:
我启动 Cli 的第一个实例:user found
我在 CLI 1 中输入“hello world”:hello world
(换行符)13
我再次在 Cli 1 中输入“hello world”:hello world
(换行符)13
我启动 Cli 的第二个实例:user found
我在 CLI 2 中输入“hello world”:hello world
(换行符)14
我再次在 Cli 2 中输入“hello world”:hello world
(换行符)14
我在 CLI 中输入“hello world”no1:hello world
(换行符)13
我再次在 CLI 1 中输入“hello world”:
我终止 Cli no1:
我终止 Cli no2:Client Lost
(换行符)Client Lost
最后的问题:
怎么会,每当我添加另一个客户端连接到服务器时,旧客户端只能在服务器停止响应之前再发送一条消息。
那是因为 Helper
class 中的 br
和 bw
声明为 static
.
static
表示该字段由 class.
的所有实例共享
因此,当为您的第二个客户端创建第二个 Helper
实例时,这些共享的 br
和 bw
会被 reader 覆盖,并为此编写新连接 => 即之后 Helper
个线程读取和写入这个新连接。
您看到旧客户端又写了一个,因为当 br
和 bw
被覆盖时,旧的 Helper
线程已经在 br.readLine()
内部等待传入来自第一个客户的字符串。
旧的 Helper
线程仅在行到达后读取 br
和 bw
的新值。
首先我想介绍一下我现在的代码:
/**
App.java:
**/
package org.example;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class App
{
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(2343);
} catch (IOException e) {
System.err.println("Could not listen on 2343");
}
try {
while (true) {
Socket clientSocket = serverSocket.accept();
try {
new Helper(clientSocket);
} catch (IOException e) {
clientSocket.close();
}
}
} finally {
serverSocket.close();
}
}
}
/**
Helper.java:
**/
package org.example;
import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class Helper extends Thread {
public static BufferedReader br;
public static BufferedWriter bw;
public static String output = "";
public Helper(Socket socket) throws IOException {
System.out.println("user found");
br = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8));
start();
}
@Override
public void run() {
while (true) {
try {
bw.write("set");
bw.newLine();
bw.flush();
System.out.println(br.readLine()+"\n"+getId());
} catch (IOException e) {
System.out.println("Client Lost");
break;
}
}
}
}
/**
Cli.java
**/
package org.example2;
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
class Cli {
public static void main(String[] argv) throws Exception {
BufferedWriter bw;
Socket clientSocket;
BufferedReader br;
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
clientSocket = new Socket("laith.com.au", 2343);
bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream(), StandardCharsets.UTF_8));
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), StandardCharsets.UTF_8));
while(true){
String input=br.readLine();
bw.write(inFromUser.readLine());
bw.newLine();
bw.flush();
}
}
}
其次我将展示输出:
App.java
user found
hello world
13
hello world
13
user found
hello world
14
hello world
14
hello world
13
Client Lost
Client Lost
Cli.java(no1 所有用户输入)
hello world
hello world
hello world
hello world
Cli.java(no2 所有用户输入)
hello world
hello world
成绩单:
我启动应用程序:
我启动 Cli 的第一个实例:user found
我在 CLI 1 中输入“hello world”:hello world
(换行符)13
我再次在 Cli 1 中输入“hello world”:hello world
(换行符)13
我启动 Cli 的第二个实例:user found
我在 CLI 2 中输入“hello world”:hello world
(换行符)14
我再次在 Cli 2 中输入“hello world”:hello world
(换行符)14
我在 CLI 中输入“hello world”no1:hello world
(换行符)13
我再次在 CLI 1 中输入“hello world”:
我终止 Cli no1:
我终止 Cli no2:Client Lost
(换行符)Client Lost
最后的问题:
怎么会,每当我添加另一个客户端连接到服务器时,旧客户端只能在服务器停止响应之前再发送一条消息。
那是因为 Helper
class 中的 br
和 bw
声明为 static
.
static
表示该字段由 class.
因此,当为您的第二个客户端创建第二个 Helper
实例时,这些共享的 br
和 bw
会被 reader 覆盖,并为此编写新连接 => 即之后 Helper
个线程读取和写入这个新连接。
您看到旧客户端又写了一个,因为当 br
和 bw
被覆盖时,旧的 Helper
线程已经在 br.readLine()
内部等待传入来自第一个客户的字符串。
旧的 Helper
线程仅在行到达后读取 br
和 bw
的新值。