Java 连接关闭时BufferReader仍在运行
我有一个稍微简单的服务器,这意味着我试图通过使服务器尽可能面向对象来学习不同的设计模式。令人惊讶的是,直到我创建了close()方法,我才发现一个问题 显然,当客户端关闭与数据库的连接时,BufferReader仍然需要输入并抛出一个执行选项,表示Java 连接关闭时BufferReader仍在运行,java,sockets,networking,Java,Sockets,Networking,我有一个稍微简单的服务器,这意味着我试图通过使服务器尽可能面向对象来学习不同的设计模式。令人惊讶的是,直到我创建了close()方法,我才发现一个问题 显然,当客户端关闭与数据库的连接时,BufferReader仍然需要输入并抛出一个执行选项,表示Java.net.socketExecOption:socketclosed 由于我有很多不同的课程,我只会张贴那些失败的,如果你需要更多的信息,请不要犹豫,给我一个评论。此外,由于我正试图从这个项目中学习,如果您愿意,请对我的代码进行评论:) 代码(
Java.net.socketExecOption
:socketclosed
由于我有很多不同的课程,我只会张贴那些失败的,如果你需要更多的信息,请不要犹豫,给我一个评论。此外,由于我正试图从这个项目中学习,如果您愿意,请对我的代码进行评论:)
代码(我所有的代码)
连接
public class Connection{
private Socket connection;
public Connection(Socket connection){
this.connection = connection;
ServerListner cl = new ServerListner(Connection.this);
cl.start();
}
public Socket getConnection(){
return this.connection;
}
public void close() {
try {
connection.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ServerListner
public class ServerListner extends Thread {
private Socket connection;
private BufferedReader br;
private ChatPerson person;
private Connection con;
private ServerInformation ai = new ServerInformation();
private ServerConnectionManager scm = new ServerConnectionManager();
private ServerSender sender = new ServerSender();
public ServerListner(Connection con){
this.con = con;
connection = con.getConnection();
try {
br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Socket getConnection(){
return this.connection;
}
public void run(){
while (con.getConnection().isConnected()) {
String inString;
try {
while ((inString = br.readLine()) != null) {
processInput(inString);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void processInput(String input){
if (input.equalsIgnoreCase("Connect")) {
sender.sendMessageToConnection(this.connection, "Accepted");
}
if (input.equalsIgnoreCase("UserInformation")) {
try {
String username = br.readLine();
person = new ChatPerson(username, connection);
ai.add(person);
System.out.println(ai.getList());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (input.equalsIgnoreCase("SearchByCon")) {
String name = ai.searchByConnection(connection);
System.out.println(name);
}
if (input.equals("Disconnect")) {
scm.closeMe(connection);
}
}
}
**服务器发送方**
public class ServerSender {
private PrintWriter pw;
private ServerInformation ai = new ServerInformation();
public void addToList(){
}
public void sendToAll(String message){
for (Connection c : ai.getConnectionList()) {
try {
pw = new PrintWriter(c.getConnection().getOutputStream());
pw.print(message);
pw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
*
* @param con
* @param message
*/
/*
* Note - Denne metode gør også at jeg kan hviske til folk!:)
*/
public void sendMessageToConnection(Socket con, String message){
try {
PrintWriter print = new PrintWriter(con.getOutputStream());
print.println(message);
print.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
**服务器信息**
public class ServerInformation {
private ArrayList<Connection> connectedClients = new ArrayList<Connection>();
private ArrayList<ChatPerson> list = new ArrayList<ChatPerson>();
public ArrayList<Connection> getConnectionList(){
return connectedClients;
}
public void addToConnectionList(Connection con){
connectedClients.add(con);
}
public String searchByConnection(Socket myConnection){
for (ChatPerson p : list) {
if (p.getConnection() == myConnection) {
return p.getName();
}
}
/*
* If none found!
*/
return null;
}
public void add(ChatPerson p){
list.add(p);
}
public void removeByName(String name){
for (ChatPerson p : list) {
if (p.getName().equalsIgnoreCase(name)) {
list.remove(p);
}
}
}
public String searchList(String name){
for (ChatPerson p : list) {
if (p.getName().equalsIgnoreCase(name)) {
return p.getName();
}
}
return null;
}
public ArrayList<ChatPerson>getList(){
return list;
}
}
我尝试了以下方法:
这不起作用,但仍然给了我相同的执行选项。上的文档说
当前在此套接字上的I/O操作中阻塞的任何线程都将抛出SocketException
您可能希望中断readline()循环并关闭此循环之外的连接。上的文档中说
while (con.getConnection().isConnected()) {
String inString;
try {
while ((inString = br.readLine()) != null) {
processInput(inString);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
当前在此套接字上的I/O操作中阻塞的任何线程都将抛出SocketException
您可能希望中断readline()循环并关闭此循环之外的连接
while (con.getConnection().isConnected()) {
String inString;
try {
while ((inString = br.readLine()) != null) {
processInput(inString);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
拥有这两个循环是没有意义的readLine()
将在到达EOS时立即返回null,此时应关闭套接字并退出循环。在任何情况下,isConnected()
都不会告诉您有关连接状态的任何信息,只会告诉您在Socket
上调用了哪些API,后者是连接的端点。失去外环
拥有这两个循环是没有意义的
readLine()
将在到达EOS时立即返回null,此时应关闭套接字并退出循环。在任何情况下,isConnected()
都不会告诉您有关连接状态的任何信息,只会告诉您在Socket
上调用了哪些API,后者是连接的端点。丢失外部循环。在SCM类中,您没有在函数closeMe中引用输入参数con。ai.getConnectionList()从哪里获取数据?您似乎忽略了您的输入,并引用了一些类变量,希望这些类变量引用列表中某个位置的相同连接,但您的类变量似乎仍然丢失。你可能会很幸运,但这次不是。我添加了我的其他类,以便它变得更清晰。但是为什么你要忽略close me方法上的输入参数?这最多只能使代码变得不清晰。@Bnjmn-im不是吗?closeMe方法获取一个套接字作为参数,我在列表中搜索该套接字,然后将其关闭。在SCM类中,您没有在函数closeMe中引用输入参数con。ai.getConnectionList()从哪里获取数据?您似乎忽略了您的输入,并引用了一些类变量,希望这些类变量引用列表中某个位置的相同连接,但您的类变量似乎仍然丢失。你可能会很幸运,但这次不是。我添加了我的其他类,以便它变得更清晰。但是为什么你要忽略close me方法上的输入参数?这最多只能使代码变得不清晰。@Bnjmn-im不是吗?closeMe方法获取一个套接字作为参数,我在列表中搜索该套接字,然后将其关闭。如果我们查看该循环的跟踪,那么它将是这样的(至少在我看来)inString=“Disconnect”->processInput(“Disconnect”)if(“Disconnect”.equals(“Disconnect”){scm.closeMe(connection);}Conn.close()回到循环,while(con.getConnection().isConnected())将为false,它将不再循环,或者我错了吗?我知道while循环现在是什么,但我如何绕过它?如果我们查看该循环的轨迹,那么它将是这样的(至少在我的脑海中)inString=“Disconnect”->processInput(“Disconnect”),如果(“Disconnect”.equals(“Disconnect”){scm.closeMe(connection);}Conn.close()返回循环,然后while(con.getConnection().isConnected())将为false,它将不再循环,或者我错了吗?我知道while循环现在是什么,但我如何绕过它?
try {
String inString;
while ((inString = br.readLine()) != null) {
if (inString.equalsIgnoreCase("Disconnect")) {
System.out.println(inString);
break;
}else {
processInput(inString);
}
}
scm.closeMe(connection);
while (con.getConnection().isConnected()) {
String inString;
try {
while ((inString = br.readLine()) != null) {
processInput(inString);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}