2010-01-31 1 views
-2

멀티 플레이어 게임에 문제가 있습니다. 지금 당장은 서버가 현재 레벨을 클라이언트로 보내도록하려고합니다. 서버가 확실히 데이터를 보내고 있지만 클라이언트 응용 프로그램에 도달하지 않습니다.Java selector/SocketChannel 문제

클라이언트 코드 :

public void run() { 
    while(true) 
    { 
     try { 
      sel.select(); 
      Set readyKeys = sel.selectedKeys(); 
      Iterator itr = readyKeys.iterator(); 
      while(itr.hasNext()) 
      { 
       SelectionKey key = (SelectionKey) itr.next(); 
       itr.remove(); 
       SocketChannel ch = (SocketChannel) key.channel(); 
       if(key.isReadable()) 
       { 
        inputbuf.clear(); 
        long bytesRead = ch.read(inputbuf); 
        inputbuf.flip(); 
        byte[] test = inputbuf.array(); 
        { 
         for(int i=0; i < inputbuf.remaining(); i++) 
         { 
          System.out.print(test[i]+" "); 
         } 
        } 
        byte cmd = 0; 
        cmd = inputbuf.get(); 
        switch(cmd) 
        { 
         case 1: 
          //do something 
         case 2: 
          //do something else 
         break; 
        } 
       } 
       else if(key.isConnectable()) 
       { 
        sc.finishConnect(); 
        sc.register(sel, SelectionKey.OP_READ); 
       } 
      } 
     } catch (IOException ex) { 
      Buildsim.error("Error handling input from server", ex); 
     } 
    } 
} 

서버 코드 :

public RemotePlayer(SocketChannel s) 
{ 
    sc = s; 
    try { 
     sel = Selector.open(); 
     sc.configureBlocking(false); 
     sc.register(sel, SelectionKey.OP_WRITE); 
     socket = sc.socket(); 
     ip = socket.getInetAddress().toString(); 
     System.out.println("New connection from "+ip); 
     inputbuf = ByteBuffer.allocate(1048576); 
     outputbuf = ByteBuffer.allocate(1048576); 
     inputbuf.clear(); 
     outputbuf.clear(); 
    } 
    catch(Exception e) 
    { 
     Buildsim.error("Connection error: ", e); 
    } 
    sendLevel(); 
} 
public void sendObject(GameObject obj) 
{ 
    //Sends a packet of the object, then does the same for the object's children 
} 
public void sendLevel() 
{ 
    try { 
     outputbuf.put((byte) 0x01); 
     outputbuf.flip(); 
     sc.write(outputbuf); 
     sendObject(Buildsim.w.parts.get(0)); //root object 
    } 
    catch(IOException e) 
    { 
     Buildsim.error("Error sending level to "+ip, e); 
    } 
} 

클라이언트에 도달 유일한 것은 바이트 0x01로 인은 (레벨 변화를 신호).

미리 감사드립니다.

+2

이 정보를 분석하고 디버깅하려고 시도한 내용을 말씀해주십시오. – bmargulies

+0

내 대답을 편집 했습니까? – rsp

답변

0

귀하가 제공 한 정보의 양과 함께 다음과 같이 글로벌 힌트 만 제공 할 수 있습니다. 소켓 스트림이 버퍼링되지 않았는지 확인하고 정보를 작성한 후에 flush()을 작성 했습니까?

데이터를 채우기 위해 대기중인 버퍼에서 데이터가 대기 할 수 있습니다.

편집 :

당신은 당신이이 송신 측에 세척을 담당 가정 맞아, 그래서 내가 그들의 입력을 버퍼링하지 않는 클라이언트를 가정, 비 블록 모드로 SocketChannel에 설정?

SocketChannel.write()은 전체 버퍼를 작성하기 위해 garantueed되지 않았을 수 있지만 초기에 반환 될 수 있습니다. 데이터가 채널에 실제로 기록되는지 확인하기 위해 작성된 바이트를 추적하려면 while 루프에서 쓰기를 래핑해야합니다. 별도의 규정이없는 한

, 쓰기 작업이 요구 된 r 바이트가 모두 작성 후 반환합니다 Javadoc을 인용합니다. 일부 유형의 채널은 상태에 따라 바이트 중 일부만 쓸 수도 있고 그렇지 않을 수도 있습니다. 비 차단 모드 소켓 채널 예를 들어, 은 소켓 출력 버퍼보다 ​​더 많은 수의 바이트를 쓸 수 없습니다.

+0

코드에서 볼 수 있듯이 ByteBuffers를 사용하여 데이터를 보유하고 있습니다. 나는 그들을 플러시 할 필요가 없다는 인상 아래에 있었고, 단지 sc.write()를 사용하여 버퍼에있는 데이터를 보냈습니까? –