이 글은 내가 작성한 첫 번째 Java 소켓/다중 스레드 응용 프로그램이므로, 여러분이 목격하려고하는 극악한 코드에 대해 사과하고 싶습니다.Java 다중 스레드 서버 - CPU 사용률이 높고 java.net.SocketException : 소켓이 닫혔습니다.
어쨌든 대부분의 사용자는이 코드를 한 번에 더 많은 클라이언트와의 연결을 허용하는 기본 서버로 간주 할 것입니다. 또한 서버에는 서버를 닫는 StopServer 버튼이있는 인터페이스가 있지만 클라이언트는 서버에 연결 한 다음 연결을 끊는 것 외에는 다른 작업을 수행하지 않습니다. 단순히 서버 클래스를 실행하는 경우
이제, 괜찮아, 아무것도 '나쁜'어떻게 내가 그것을 닫을 때, 그것은하지만, 잘 닫습니다 : 나는 서버 클래스를 실행하는 경우, 다음 :
1 내가 한 번 클라이언트 클래스를 실행하는 서버를 닫으려고 다음 클라이언트 차단을하자, 나는 오류를 얻을 :
java.net.SocketException: socket closed
2 : 각 클라이언트는 CPU 사용률 ~ 30-35%에 대해 추가합니다 단지 짧은 실행이고, 그 이용은 "Java (TM) Platform SE Binary"프로세스에 남아있을 것이다. 계속 실행됩니다. 클라이언트를 서버에 연결하면 30 초, CPU 사용률은 100 %에 도달합니다.
또한 약간의 연구를했으며 "소켓 폐쇄 예외"는 소켓을 닫은 다음 계속 사용하려고 시도했음을 의미하며 서버가 서버를 처리하는 방법에도 문제가있을 수 있음을 알고 있습니다. 연결이 끊어진 클라이언트. 위의 코드의 라인 65에 :
서버
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의'
여기에 코드입니다. 이것이 내가 현재 구축하고있는 전체 응용 프로그램의 단지 조각이다
클라이언트
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 문제도 가지고 있습니다. 나는 이른바 '비슷한'질문에서 답을 얻을 수 없다.
중복되었지만 관련 코드를 모두 생략했습니다. 내부에서 'IOException' *을 무시하면 루프가 시작됩니다. – EJP
@EJP 글쎄, 내가 왜 위에서 언급 한 일이 일어 났는지 알고 싶다. 그래서 나는 문제와 관련있는 코드 부분을 추가하는 것이 최선의 방법이라고 생각한다. 둘째로, "루프 내부의 IOException을 무시하는 것이 무엇인지"에 대해 더 자세히 설명 할 수 있다면, 해결해야 할 부분과해야 할 일에 대해 고맙게 생각합니다. 셋째, 어떻게 복제본인지 알지 못합니다. 문제는 분명합니다. 소켓의 출력 스트림을 닫은 다음 입력을 사용하려고합니다. 동시에 모든 것을 함께 닫습니다. 또한, 나는 또한 그의 질문에 해결되지 않은 CPU 문제가있어. –
그것은 소켓을 닫은 다음 계속 사용하고 그렇게하는 예외를 무시하기 때문에 발생합니다. 모든 노력이 힘들다. '루프 안에서 IOException'을 무시하는 것에 대한 해결책은 루프 내에서 'IOException'을 무시하고 * stop *하는 것을 * 찾기 *하는 것입니다. 흑인과 백인이 있습니다. 나는 그것을 발견했다 : 당신도 할 수있다. 결국 당신은 그것을 썼습니다. – EJP