2014-02-23 3 views
0

원격 서버와 통신하기 위해 SocketChannel을 사용하고 있습니다. 그러나 오류 및 예외없이 socketChannel.write()를 사용하여 데이터를 보내지 만 서버 로그는 데이터가 수신되지 않았 음을 나타냅니다. 클라이언트 tcp 트래픽 모니터는 또한 ByteBuffer의 문자열 메시지가 전송되지 않았 음을 보여줍니다.SocketChannel write()는 오류없이 반환하지만 실제로 데이터가 전송되지 않았습니다.

아무에게도 이것이 왜 그런지 힌트를 줄 수 있습니까? 고맙습니다!

public class Client implements Runnable { 
    SocketChannel socketChannel; 
    Selector selector; 
    SelectionKey key; 
    ByteBuffer inbuf, outbuf; 
    int id; 
    @Override 
    public void run() { 
    try { 
     // prepare inbuf and outbuf 
     inbuf = ByteBuffer.allocate(10000); 
     outbuf = ByteBuffer.allocate(10000); 

     // prepare a socket channel for communication 
     socketChannel = SocketChannel.open(); 
     socketChannel.connect(new InetSocketAddress("<remote server ip>",)); 
     selector = Selector.open(); 
     socketChannel.configureBlocking(false); 
     key = socketChannel.register(selector, SelectionKey.OP_READ 
       | SelectionKey.OP_WRITE); 

     while (selector.select() > 0) { 

      if (key.isReadable()) { 
       // read from channel when server sends data 
       read(); 
      } 

      if (key.isWritable()) { 
       // write 
       Random r = new Random(500); 
       write("b", r.nextInt(), r.nextInt()); 
       for (int i = 0; i < 10; i++) { 
        // write a message to server after 1 second 
        Thread.sleep(1000); 
        write("m", r.nextInt(), r.nextInt()); 
       } 
       write("e", r.nextInt(), r.nextInt()); 
      } 
     } 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 

private void write(String action, int x, int y) throws IOException { 
    String msg = String.format("%s:%d:%d:%d", action, id, x, y); 
    int r=outbuf.remaining(); 

    outbuf.put(msg.getBytes()); 
    int rBytes = outbuf.remaining(); 
    boolean connected = socketChannel.isConnected(); 
    Socket sock = socketChannel.socket(); 

    if (connected && sock.isConnected() && !sock.isOutputShutdown()) 
>>>>>>>>>> socketChannel.write(outbuf); 
    else 
     System.out.println("Connection broken!"); 

    System.out.printf("Client %d told server:%s\n", id, msg); 
    //outbuf.clear(); 
} 

    ... //read omitted here 
+0

당신이)합니다 (ByteBuffer를 플립나요 :) 트릭을 할해야 풋 후 buffer.flip()를 추가? 편집 : 아니, 당신은 ... 나는 대답을 쓰고있어. – xp500

+0

고마워요! 안녕하세요 @ EJP, 나 한테 물어 보는 또 다른 질문을 좀 해보시겠습니까? 고맙습니다. http://stackoverflow.com/questions/21965436/socketchannel-selector-vs-plain-socket?lq=1 – wizoleliam

답변

5

버퍼에 내용을 넣거나 내용을 읽은 후 버퍼를 뒤집어 써서 데이터를 쓰거나 가져와야합니다. Buffer 클래스의 flip() 메서드를 확인하십시오. 문서 내용

이 버퍼를 뒤집습니다. 한계가 현재 위치로 설정되고 위치가 0으로 설정됩니다. 마크가 정의되어 있다면 그것은 버려집니다. 일련의 채널 읽기 또는 작업 후,이 메소드를 호출하여 일련의 채널 쓰기 또는 상대적인 get 조작을 준비한다.

그래서

+0

+1 그리고'write(). '에 의해 반환 된 값을 무시하지 않는다. 사건으로 경보 음이 울려 야합니다. – EJP

+0

감사합니다 @ xp500, 작동합니다! ByteBuffer 또는 Buffer 클래스는 일반적으로 읽기 및 쓰기 모드 사이에서 '대칭 이동'될 수 있습니다. 이것이 작동하기 때문에 ByteBuffer에 몇 바이트를 넣으면 SocketChannel write() 메서드가 실제로 버퍼를 읽고 socket의 outputStream을 통해이를 쓰게 될까요? 감사합니다 – wizoleliam

+0

@ EJP, 당신의 힌트를 가져 주셔서 감사합니다! – wizoleliam