2015-01-11 5 views
0

Java로 네트워크 소프트웨어를 프로그래밍하고 있지만 "true"네트워크를 통해 응용 프로그램을 사용하는 데 실제 문제가 있습니다.소켓이 LAN 또는 NET에서 제대로 작동하지 않지만 완벽하게 로컬로 작동합니다.

소프트웨어를 호스트로 설정하고 클라이언트 연결을 수신하도록 지정하십시오. 여기 내 서버 루프 :

public void run() {                
    try {                  
     ObjectOutputStream out = new ObjectOutputStream(mSocket.getOutputStream());                     
     ObjectInputStream in = new ObjectInputStream(mSocket.getInputStream()); 

     while(mSocket.isConnected() && !mSocket.isClosed()) {     
      for (int i = 0; i < mOutMessages.size(); i++) {      
       Message msg = mOutMessages.get(i);        
       out.writeObject(msg);           
      }                 
      out.flush();               
      mOutMessages.clear();            

      Thread.sleep(50);             
      out.reset();               

      while(true) {              
       try {               
        Message m = (Message) in.readObject();      
        mInMessages.add(m);           
       } catch (Exception e) {           
        break;              
       }                
      }                 

      Thread.sleep(50);             
     }                  
    } catch(Exception ex) {              
     try {                 
      mSocket.close();              
     } catch(Exception exx) {             
      exx.printStackTrace();            
     }                  
     ex.printStackTrace();             
    }                   
}                    

: 여기

public Client connect(InetAddress addr, int port) throws Exception { 
    Socket socket = new Socket(addr, port);       
    socket.setSoTimeout(50);          
    socket.setTcpNoDelay(false);         
    Client c = new Client(socket);         
    c.start();              
    return c;              
}                 

그리고 클라이언트 루프가된다

public void run() {             
    while (mServerSocket != null) {           
     try {                
      Socket wClient = mServerSocket.accept();      
      System.out.println("Client connecté");       
      wClient.setSoTimeout(50);          
      wClient.setTcpNoDelay(false);         
      Client c = new Client(wClient);         
      synchronized(this) {           
       mWaitingClients.add(c);          
       c.start();             
      }                
     } catch(Exception ex) {            
      System.out.println("Server error : " + ex.getMessage());  
     }                 
    }                  
}                   

클라이언트가 서버에 연결을 시도,이 기능을 사용 프로그램의 다른 부분은 Message를 수행하여 클라이언트 (mOutMessages)의 출력 목록에 넣습니다. 프로그램의 일부 다른 부분은 클라이언트의 mInMessages에서 메시지를 읽습니다.

하지만 뭔가 잘못되었습니다. 로컬 (서버 및 동일한 컴퓨터의 클라이언트)에서 제대로 작동하지만 LAN 또는 인터넷을 통해 두 대의 컴퓨터를 사용하여 실패하거나 위험합니다 (일부 메시지는 보내지 만 수신되지는 않음). 서버는 클라이언트와의 연결을 감지하고 "핸드 셰이크"메시지를 클라이언트로 보내지 만 클라이언트는 메시지를받지 못합니다.

저는 Java 프로그래머보다 C 프로그래머입니다. libc 소켓을 사용하면 이런 종류의 문제가 발생하지 않으므로, 왜 내 방식이 잘못 되었습니까?

감사합니다.

편집

: 내 서버는이 기능을 사용하여 만들어집니다 : 편집

public void open(int port) throws Exception { 
    mServerSocket = new ServerSocket(port); 
    start(); // Call the run mentionned above.         
}            

: 여기 내 솔루션, 어쩌면 완벽은 아니지만 작동!

public void run() {               
    try {                 
     BufferedOutputStream buf_out = new BufferedOutputStream(   
      mSocket.getOutputStream()          
     );                 
     BufferedInputStream buf_in = new BufferedInputStream(    
      mSocket.getInputStream()          
     );                 
     ObjectOutputStream out = new ObjectOutputStream(buf_out);   
     out.flush();              
     ObjectInputStream in = new ObjectInputStream(buf_in);    

     while(mSocket.isConnected() && !mSocket.isClosed()) {    
      for (int i = 0; i < mOutMessages.size(); i++) {     
       Message msg = mOutMessages.get(i);       
       out.writeObject(msg);          
       out.flush();            
      }                
      mOutMessages.clear();           
      out.reset();             

      while(true) {             
       try {              
        Message m = (Message) in.readObject();     
        mInMessages.add(m);          
       } catch (Exception e) {          
        break;             
       }               
      }                
     }                 
    } catch(Exception ex) {             
     try {                
      mSocket.close();            
     } catch(Exception exx) {           
      exx.printStackTrace();           
     }                 
     ex.printStackTrace();            
    }                  
+0

"실패"하면 다음은 어떻게됩니까? –

+0

서버는 ObjectOutputStream에 메시지를 쓰지만 클라이언트는 메시지를 보지 못합니다. – user3468844

+0

서버는 어떻게 만듭니 까? 아마도 –

답변

0

그렇다면 클라이언트와 서버 모두 run 방법을 사용합니다. 클라이언트와 서버 모두 충분한 메시지를 작성하면 (관련 버퍼에 적합하지 않음) 동시에 교착 상태이됩니다. 둘 다 파트너가 읽기로 진행하기 때문에 (전체 버퍼가 비울 것입니다). 네트워크 지연으로 인해 로컬이 아닌 시나리오에서만 발생할 수 있습니다. 즉, mOutMessages 버퍼에 충분한 메시지를 쌓을 수있는 충분한 시간이있을 수 있습니다.

Socket.setSoTimeout (사용했던) 설명서는 read()에 영향을 미친다는 점에 유의하십시오. 예를 들어, JDK에서는, ObjectOutputStream는 1024 바이트의 버퍼 사이즈를 가지는 BlockDataOutputStream를 사용하고있는 것처럼 보입니다.

읽고 쓰는 데 별도의 스레드를 사용하거나 최대 메시지 크기를 알고있는 경우 BufferedOutputStreamSocketOutputStream을 래핑하여 충분히 큰 버퍼를 사용하는 것이 좋습니다. 더 큰 버퍼를 선택하면 한 번에 하나의 메시지를 쓰고 (그리고 각각의 메시지를 읽으려고 시도 할 수도 있습니다).

+0

: 나는 잘못된 패킷을 얻을 버퍼에 넣으면 이제는 완벽하게 작동합니다. 내가 한 일을 보여주기 위해 내 메시지를 편집합니다 (완벽하지는 않지만 오 예!). 감사합니다. – user3468844

+0

지금은 잘 듣는 것이 좋다. 내 JDK 소스에 따르면 단지 8192 바이트 (기본값)의 버퍼를 사용하고있다. Java 런타임 내부 (즉, 기본 버퍼 크기)에 종속되지 않도록 BufferedOutputStream을 구성 할 때 명시 적으로 편안한 버퍼 크기를 전달하거나 향후 개체 크기가 커질 경우 추가 공간을 추가 할 수 있습니다. – halfbit

+0

좋아, 나는 그들의 크기를 512kb로 설정했다. 감사합니다. :) – user3468844

관련 문제