2013-02-07 3 views
0

나는 클라이언트/서버 자바 게임을하고있다. 가능한 많은 코드와 메신저가 가능한 한 많이 붙여 넣기를 시도하면서 충분합니다.사용하지 않을 때에도 많은 CPU를 사용하는 서버 프로그램

처음 서버를 시작하면 CPU가 필요하지 않습니다. 첫 번째 게임 클라이언트가 연결되면 25 %로 점프합니다 (게임에 비해 상당히 높지만 내 관심사는 아직 없습니다). 문제는 클라이언트가 연결을 끊어도 서버 응용 프로그램의 CPU 사용이 25 %로 유지됩니다.

서버는 클라이언트에서 이름을 가져 와서 플레이어로부터 x, y 좌표를 지속적으로받습니다. 여기

TCPServer(int port) { 
       try 
       { 
         tcpSock = new ServerSocket(port); 
         int z = 0; 
         while(true) 
         { 
           Socket sock = tcpSock.accept(); 
           sock.setKeepAlive(true); 
           clientList.addElement(new TcpClient(sock)); 
           clientList.get(z).cr.start(); 
           clientList.get(z).cw.start(); 
           clientList.get(z).packs.addElement("?"); 
           while(!clientList.get(z).cr.nameRecieved) 
           { 
           //do nothing untill client has provided it's name 
           } 
           playerList.addElement(new player(sock.getInetAddress(), clientList.get(z).cr.playerName));          
           playerList.get(z).id=z; 
           playerList.get(z).name=clientList.get(z).cr.playerName; 
           clientList.get(z).packs.addElement("2 " + z); 
           for(int j =0; j<playerList.size();j++) 
            { 
            String status; 
            if(playerList.get(j).Connected) 
             status = "1"; 
            else 
             status = "0"; 

             addToQueue("3 " + playerList.get(j).id + " " 
               + playerList.get(j).name + " " + playerList.get(j).x + " " + playerList.get(j).y + " " + 
               playerList.get(j).area + " " + status + " ");      
            } 
           z++; 
           addToQueue("4 " + z); 
         }  
       } 

       catch (IOException e) { 
         System.out.print(e); 
       } 
     } 

(나는 과도한 들여 쓰기 위해 사전에 사과)와 각 클라이언트에 대해 실행되는 코드입니다 : 여기

서버가 시작되면 실행되는 내 실제 서버의 코드입니다. 나는 가독성을 위해 많은 부분을 주석 처리했으며 코드는 다양한 위치 정보를 계산하고 업데이트합니다. 문제는이 수업에서 어딘가에서 발생하고 있다고 생각합니다.

public class TcpClient { 
       Socket sock; 
       ObjectInputStream in; 
       ObjectOutputStream out; 
       ClientRead cr; 
       ClientWrite cw; 
       public Vector<String> packs = new Vector<String>(); 
       TcpClient(Socket s) { 
         this.sock = s; 
         try 
         { 
          sock.setKeepAlive(true); 
         } 
         catch(Exception e) 
         { 
          System.out.print(e); 
         } 
         cr = new ClientRead(); 
         cw = new ClientWrite(); 
       } 
       public class ClientRead extends Thread { 
        public boolean nameRecieved = false; 
        public boolean reading = true; 
       String playerName; 
        public void run(){ 
         try{ 
          in = new ObjectInputStream(sock.getInputStream()); 
          while(sock.isConnected() && reading) 
          { 
           //code to retrieve and update user location 
          } 
         } 
         catch(Exception e){ 
           System.out.print(e); 
        } 
       } 
     } 

그리고 마지막으로, 짧은 클래스는 클라이언트에 정보를 기록하기 :

public class ClientWrite extends Thread { 
       public boolean writing = true; 
        public void run() { 
         try{ 

          out = new ObjectOutputStream(sock.getOutputStream()); 
          out.flush(); 
          while(sock.isConnected() && writing) 
          { 
           out.flush(); 
           while(!packs.isEmpty()) 
           { 
            out.writeObject(packs.firstElement()); 
            System.out.print(packs.firstElement()); 
            packs.remove(0); 
            out.flush(); 
           } 
          } 

         } 
         catch(Exception e) 
         { 
          System.out.print(e); 
         } 
        } 
       } 

나는 코드의 톤이 알고 있지만, 누군가가 바로 (특히 스레드) 밖으로 점프 anyting를 볼 경우 그 메신저의 행동을 설명 할 수 있습니다. 요약하면 서버는 클라이언트가 연결할 때까지 0 % cpu로 유지됩니다. 첫 번째 클라이언트가 연결된 후에 아무리 많은 연결이 있더라도 CPU 점유율은 25 % -30 %입니다. 클라이언트의 모든 연결이 해제 한 경우에는, CPU는 여기에 0

+1

BTW는 쿼드 코어 프로세서에서 25 % CPU가 아마 1 코어의 100 %라고합니다. 그 스레드는 가능한 한 많은 CPU 시간을 사용하고 있습니다. – Wyzard

+0

@BevynQ 스레드는 '폴링 스타일 필요 없음'입니다. 블로킹 모델을 사용할 수 있습니다. 그것이 당신이 그들을 사용하는 이유입니다. – EJP

답변

5

문제로 다시 내려가는 -30 % 대신에 25 %로되어 숙박 :

while(!clientList.get(z).cr.nameRecieved) 
{ 
    //do nothing untill client has provided it's name 
} 

그것은 스핀 루프입니다 CPU를 연기가 난다. 너는이 모든 것을 잘못하고있다. 소켓을 수락하면 즉시 새 스레드를 시작하여 소켓을 처리해야합니다. 그 스레드블록이어야합니다. 클라이언트가 프로토콜 핸드 셰이크의 일부로 이름을 제공 한 다음 데이터 구조를 업데이트 할 때까지. accept 루프는 accept 연결과 start 스레드를 제외하고는 아무 것도하지 않습니다.

+0

+1 효율적입니다. –

+0

고마워요, 이것에 대해 살펴 보겠습니다. –

관련 문제