0

현재 클라이언트에서 서버로 객체를 보내거나 그 반대로 객체를 보낼 수있는 서비스를 만들고 있지만, 설명 할 수없는 문제가 있습니다.소켓과 쓰레드를 제대로 사용하지 않고 소켓과 쓰레드를 사용하여 객체를 보내고받는 것.

우선, 유용한 클래스가 있습니다 (이 게시물에는 getters 및 setters와 같은 모든 메소드를 넣지 않았습니다). 당신이 ServerLauncher과 ClientLauncher에서 눈치 챘을 수도 그래서 기본적으로


/** 
* This class handles every incoming messages. 
*/ 
public class ReceiveManager implements Runnable { 

    private ObjectInputStream inputStream; 
    private CommunicationManager communicationManager; 
    private List readObjects; 
    private boolean receive; 

    public ReceiveManager(CommunicationManager communicationManager) throws IOException { 
     this.communicationManager = communicationManager; 
     this.inputStream = new ObjectInputStream(this.communicationManager.getSocket().getInputStream()); 
     this.readObjects = new ArrayList(); 
     this.receive = true; 
    } 

    @Override 
    public void run() { 
     Object object = null; 

     try { 
      while ((object = this.inputStream.readObject()) != null && this.hasToReceive()) { 
       this.readObjects.add(object); 
      } 
     } catch (ClassNotFoundException | IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
      this.setContinueToReceive(false); 
     } 
    } 

    private boolean hasToReceive() { 
     return this.receive; 
    } 

    public void setContinueToReceive(boolean value) { 
     this.receive = value; 
    } 
} 

/** 
* This class allows the user to send messages 
*/ 
public class SendManager { 

    private ObjectOutputStream outputStream; 
    private CommunicationManager communicationManager; 

    public SendManager(CommunicationManager communicationManager) throws IOException { 
     this.communicationManager = communicationManager; 
     this.outputStream = new ObjectOutputStream(this.communicationManager.getSocket().getOutputStream()); 
    } 

    public void send(Object object) throws IOException { 
     this.outputStream.writeObject(object); 
     this.outputStream.flush(); 
    } 
} 


/** 
* This launcher creates a NetworkSystem, connects to the server, waits for an incoming message and anwers back 
* 
*/ 
public class ClientLauncher { 

    public static void main(String[] args) { 
     try { 
      NetworkSystem n = new NetworkSystem(8192); 
      n.instanciateCommunication(new Socket(InetAddress.getLocalHost(), 4096)); 

      while (n.getCommunications().get(0).getReceiveManager().getReadObjects().isEmpty()) { 
       // this line is unexpectedly magic 
       System.out.println("Waiting for an object..."); 
      } 

      System.out.println(n.getCommunications().get(0).getReceiveManager().getReadObjects().get(0)); 
      n.getCommunications().get(0).getSendManager().send(new String("No, I am not! We will talk later...")); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 


/** 
* This launcher creates a NetworkInterface, waits for a connection, sends a message to the connected client and waits for an incoming message 
* 
*/ 
public class ServerLauncher { 

    public static void main(String[] args) { 
     try { 
      NetworkSystem n = new NetworkSystem(4096); 
      n.startServerManager(); 

      while (n.getCommunications().isEmpty()) { 
       // this line is unexpectedly magic 
       System.out.println("Waiting for a new connection..."); 
      } 

      do { 
       n.getCommunications().get(0).send(new String("Hello, are you available?")); 
      } while (n.getCommunications().get(0).getReceiveManager().getReadObjects().isEmpty()); 

      System.out.println(n.getCommunications().get(0).getReceiveManager().getReadObjects().get(0)); 

     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 
,이 "마법"지침이있다. 이 두 줄을 주석 처리하고 서버를 실행 한 다음 클라이언트를 실행하면 아무 일도 일어나지 않습니다. 서버와 클라이언트는 단순히 실행되고 멈추지 않습니다. 그러나이 두 마술 라인의 주석을 없애면 모든 것이 매력처럼 작동합니다. 메시지는 제대로 보내고받을 수 있습니다.

이 예기치 않은 동작의 원인을 알고 계실까요? 너희들이 나를 그냥 당신은 그 스핀 루프와 CPU를 굶주리고있는

답변

0

:-) 말해, 프로젝트 또는 무엇이든을 테스트 할 모든 것을 업로드하려면

는 오, 그래, 나는 잊어 버렸습니다. 대기열이 비어있는 동안 대기하거나 기다려야하며 더 좋게는 여전히 take() 대기열에서 대기해야합니다.

루프 조건을주의하는 것은 올바르지 않습니다 :

  1. readObject()

    이 스트림의 마지막에 null를 반환하지 않습니다. 그것은 EOFException을 던졌습니다.
  2. hasToReceive() 전에 테스트해야합니다. 나중에 readObject()으로 호출해야합니다. 그렇지 않으면 항상 추가 읽기를 수행합니다.