gpt4 book ai didi

Java 多线程服务器 - 高 CPU 利用率和 java.net.SocketException : socket closed

转载 作者:行者123 更新时间:2023-11-30 02:34:37 24 4
gpt4 key购买 nike

这是我编写的第一个 java 套接字/多线程应用程序,因此我想为您即将看到的残暴代码表示歉意。

无论如何,大多数人可能会认为这段代码是基本的,是一个允许同时连接更多客户端的标准服务器。此外,服务器有一个只有 StopServer 按钮的界面,该按钮可以关闭服务器,同时客户端除了连接到服务器然后断开连接之外不执行任何其他操作。

现在,如果我只是运行服务器类,那就没问题,不会发生任何“不好”的事情,并且当我关闭它时,它会正常关闭,但是:

1:如果我运行服务器类,然后运行客户端类一次,让客户端断开连接,然后尝试关闭服务器,则会收到错误:

java.net.SocketException: socket closed

2:每个客户端都会在短暂的运行中增加大约 30-35% 的 CPU 利用率,并且该利用率将保持在“Java(TM) Platform SE Binary”进程中,只要服务器继续运行。如果我让客户端连接到服务器,比如说 30 秒,CPU 利用率将达到 100%。

另外,我做了一些研究,我知道“套接字关闭异常”意味着您关闭了套接字,然后继续尝试使用它,并且服务器处理断开连接的客户端的方式也可能有问题.

代码如下:

服务器

import java.sql.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;



public class Server extends JFrame
{ private Connection con;
private static int port = 44444;
private boolean serverKeepGoing;
private static int uniqueId;
private ArrayList<ClientThread> al;
private ServerSocket serverSocket;
public Scanner keyboard = new Scanner(System.in);

public static void main(String[] args) throws IOException
{ Server server = new Server(port);
server.start();

}


public void ServerClose()
{
serverKeepGoing = false;
try
{
for(int i = 0; i < al.size(); ++i)
{ ClientThread tc = al.get(i);
try
{
tc.in.close();
tc.out.close();
tc.socket.close(); }
catch(IOException e) { e.printStackTrace(); }

serverSocket.close();}

}catch(Exception e) { e.printStackTrace(); }
}


public Server (int port)
{

serverInterface();
al = new ArrayList<ClientThread>();
}




public void start()
{ serverKeepGoing = true;

try
{ serverSocket = new ServerSocket(port);
System.out.println("Server is running!");

while(serverKeepGoing)
{ Socket socket = serverSocket.accept(); // accept connection. LINE 65
// ^ALSO :java.net.SocketException: socket closed
// if I was asked to stop



if(!serverKeepGoing)
{ ServerClose(); break;}

ClientThread t = new ClientThread(socket); // make a thread of it
al.add(t); // save it in the ArrayList
t.start();


}



ServerClose(); // means the server has got to be closed

}catch (IOException e) { e.printStackTrace(); System.out.println("Error in method start"); }


}


public synchronized void remove(int id) {
// scan the array list until we found the Id
for(int i = 0; i < al.size(); ++i) {
ClientThread ct = al.get(i);
// found it
if(ct.id == id) {
al.remove(i);
return;
}
}
}



class ClientThread extends Thread
{ // the socket where to listen/talk
Socket socket;
BufferedReader in;
PrintWriter out;
boolean clientKeepGoing;
// my unique id (easier for deconnection)
int id;


public ClientThread(Socket socket)
{ id = ++uniqueId;
this.socket = socket;

try
{

in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);


}
catch (IOException e) { return; }


}


public void run()
{
boolean clientKeepGoing = true;
while(clientKeepGoing)
{ try
{





}catch(Exception e){ e.printStackTrace(); }


}
// remove myself from the arrayList containing the list of the
// connected Clients
remove(id);
close();
}


// try to close everything
private void close()
{ clientKeepGoing = false;
try {
if(out != null) out.close();
}
catch(Exception e) {}
try {
if(in != null) in.close();
}
catch(Exception e) {};
try {
if(socket != null) socket.close();
}
catch (Exception e) {}

}


}

public void serverInterface(){
JFrame frame = new JFrame("Server");

frame.setLayout(null);

int windowWidth = 300;
int windowHeight = 400;

frame.setBounds(250, 150, windowWidth, windowHeight);

JButton stopServer = new JButton("Stop server");

stopServer.setFocusable(false);

stopServer.setBounds(60, 275, 175, 20);

frame.add(stopServer);

stopServer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
ServerClose();
System.exit(1);
}
});



frame.setResizable(false);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setVisible(true);
}


public void windowClosing(WindowEvent e)
{ ServerClose();
System.exit(1);
}
public void windowClosed(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
}

“java.net.SocketException:套接字已关闭”位于上述代码的第 65 行。

客户端

import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;

public class Client
{ private BufferedReader in;
private PrintWriter out;
private Socket socket;
private int port;
private String server;


public static void main(String[] args)
{ int portNumber = 44444;
String serverAddress = "localhost";

Client client = new Client(serverAddress, portNumber);

if(!client.start())
return;

}


public Client(String server, int port)
{ this.server = server;
this.port = port;
}



public boolean start()
{ // try to connect to the server
try {
socket = new Socket(server, port);
}
// if it failed not much I can do
catch(Exception ec) {
System.out.println("Error connectiong to server:" + ec);
ec.printStackTrace();
return false;
}


try
{
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);;
}
catch (IOException eIO) {
System.out.println("Exception creating new Input/output Streams: " + eIO);
eIO.printStackTrace();
return false;
}

// creates the Thread to listen from the server
new ListenFromServer().start();


// success we inform the caller that it worked
return true;
}





class ListenFromServer extends Thread
{
public void run()
{ while(true)
{




disconnect() ;
break;
}
}


}

public void disconnect()
{ try {
if(in != null) in.close();
}
catch(Exception e) {} // not much else I can do
try {
if(out != null) out.close();
}
catch(Exception e) {} // not much else I can do
try{
if(socket != null) socket.close();
}
catch(Exception e) {} // not much else I can do
}

}

请注意,这只是我当前正在构建的整个应用程序的一部分,我试图仅发布与服务器客户端通信有关的内容,所以我删除了其他所有内容,我这样说是为了以防万一您看到一些可能没有任何目的的东西,我可能忽略了删除它

<小时/>

我发现该问题被标记为重复,我认为这是不公平的。首先,在“类似”问题中,问题很明显,输出流被关闭,从而关闭了套接字,但套接字仍然被使用,同时,我的程序关闭了所有内容,并且还存在我提到的CPU问题,对于我无法从所谓的“类似”问题中得到任何答案。

最佳答案

CPU 利用率高是因为您的客户端线程除了用空循环消耗 CPU 之外没有做任何其他事情。至于SocketException,它按计划工作,因此捕获它并处理它。

关于Java 多线程服务器 - 高 CPU 利用率和 java.net.SocketException : socket closed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43424863/

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