SocketChannel의 read 메쏘드는 timeout이 존재하지 않습니다.
혹, SocketChannel 객체의 .socket() 메쏘드로  소켓객체의  타임아웃을 세팅해도 먹지 않죠.. ^^;;
그래서, non-blocking의 read 메쏘드에 대한 timeout은 busy waiting하는 형태로 타임아웃을 줄 수 있겠습니다..

                // 20초               
                long timeout = 20 * 1000;  
                long stime = new Date().getTime();
                long rtime = 0L;
               
                int rvalue =0;
                int rvalues = 0;
                while (rtime < timeout ) {
                    rtime = System.currentTimeMillis() - stime;
                    rvalue = channel.read(rbuffer);
                    if(rvalue == -1)
                        throw new Exception("connection closed");
                   
                    rvalues = rvalues + rvalue;
                    if(rtime > timeout)
                        throw new Exception("read timeout exception");

                    if(rvalues >= 4)
                        break;
                }

저작자 표시
non-blocking SocketChannel에서 끝까지 읽어오는 코드입니다.
개인적으로 헤더 8byte, 헤더의 앞의 4byte를 전체 패킷을 길이로 잡습니다.
그리고, 아래처럼 SocketChannel에서 packet handling variables와 같이 패킷을 끝까지 다 읽어 들입니다.
아래 내용은 non-block으로 대용량의 바이너리 데이타를 읽어들이기 위해서 꼭 필요한 내용일 듯 합니다.

* read() 내용

    //// packet handling variables
    private int fullsize = 0;
    private int readedsize =0;
    private int minsize = 8;
   
    @Override
    public void read() {       
        try {
            // 읽기
            int rbytes = this.channel.read(rbuffer);
                   
            // 연결종료
            if (rbytes == -1) {
                ((ChannelListener)this.listener).disconnected(this);
                this.close();
                return;
            }
   
            // 버퍼에 내용이 없는 경우
            if (rbytes == 0) {
                this.channel.configureBlocking(false);
                this.handle();
                return;
            }
           
            // 읽은 바이트 갯수를 증감시킨다.
            readedsize += rbytes;   
            rbufferList.add(this.copy(this.rbuffer, rbytes));
           
            // 최소 패킷의 길이에서 패킷을 전체 길이를 리턴한다.
            if(readedsize >= minsize && this.fullsize == 0) {
                this.fullsize = this.createResultBuffer().getInt();
                for(int i=0; i< this.rbufferList.size(); i++) {
                    this.rbufferList.get(i).position(0);
                }
            }
           
            // 패킷을 다 읽어 들였다.
            if(fullsize == readedsize) {
                ((ChannelListener)this.listener).arrived(this,this.createResultBuffer());
            }
           
            this.channel.configureBlocking(false);
            this.handle();
        } catch(Exception e) { // disconnected
            try {
                this.close();
            } catch(IOException ie) {
                new CallbackExceptionHandler().handle(ie);
            }
           
            ((ChannelListener)this.listener).disconnected(this);
        }
    }

저작자 표시
자바는 unsigned primitive type을 지원하지 않습니다.
따라서, unsigned type을 사용할 수 있는 C/C++ 상호 호환을 위해서 Java쪽에서 unsigned type의 처리가 필요합니다. 아래의 코드는 http://www.javafaq.nu/java-example-code-342.html 에서 스크랩을 했습니다.

package com.ronsoft.books.nio.buffers;

import java.nio.ByteBuffer;

/**
 * Utility class to get and put unsigned values to a ByteBuffer object.
 * All methods here are static and take a ByteBuffer object argument.
 * Since java does not provide unsigned primitive types, each unsigned
 * value read from the buffer is promoted up to the next bigger primitive
 * data type.  getUnsignedByte() returns a short, getUnsignedShort() returns
 * an int and getUnsignedInt() returns a long.  There is no getUnsignedLong()
 * since there is no primitive type to hold the value returned.  If needed,
 * methods returning BigInteger could be implemented.
 * Likewise, the put methods take a value larger than the type they will
 * be assigning.  putUnsignedByte takes a short argument, etc.
 *
 * @author Ron Hitchens (ron@ronsoft.com)
 * @version $Id: Unsigned.java,v 1.1 2002/02/12 22:06:44 ron Exp $
 */
public class Unsigned {
   public static short getUnsignedByte (ByteBuffer bb){
      return ((short)(bb.get() & 0xff));
   }

   public static void putUnsignedByte (ByteBuffer bb, int value){
      bb.put ((byte)(value & 0xff));
   }

   public static short getUnsignedByte (ByteBuffer bb, int position){
      return ((short)(bb.get (position) & (short)0xff));
   }

   public static void putUnsignedByte (ByteBuffer bb, int position,int value){
      bb.put (position, (byte)(value & 0xff));
   }

   // ---------------------------------------------------------------

   public static int getUnsignedShort (ByteBuffer bb){
      return (bb.getShort() & 0xffff);
   }

   public static void putUnsignedShort (ByteBuffer bb, int value){
      bb.putShort ((short)(value & 0xffff));
   }

   public static int getUnsignedShort (ByteBuffer bb, int position){
      return (bb.getShort (position) & 0xffff);
   }

   public static void putUnsignedShort (ByteBuffer bb, int position, int value){
      bb.putShort (position, (short)(value & 0xffff));
   }

   // ---------------------------------------------------------------

   public static long getUnsignedInt (ByteBuffer bb){
      return ((long)bb.getInt() & 0xffffffffL);
   }

   public static void putUnsignedInt (ByteBuffer bb, long value){
      bb.putInt ((int)(value & 0xffffffffL));
   }

   public static long getUnsignedInt (ByteBuffer bb, int position){
      return ((long)bb.getInt (position) & 0xffffffffL);
   }

   public static void putUnsignedInt (ByteBuffer bb, int position, long value){
      bb.putInt (position, (int)(value & 0xffffffffL));
   }

   // ---------------------------------------------------

   public static void main (String [] argv) throws Exception {
      ByteBuffer buffer = ByteBuffer.allocate (20);

      buffer.clear();
      Unsigned.putUnsignedByte (buffer, 255);
      Unsigned.putUnsignedByte (buffer, 128);
      Unsigned.putUnsignedShort (buffer, 0xcafe);
      Unsigned.putUnsignedInt (buffer, 0xcafebabe);

      for (int i = 0; i < 8; i++) {
         System.out.println ("" + i + ": "
            + Integer.toHexString ((int)getUnsignedByte (buffer, i)));
      }

      System.out.println ("2: " + Integer.toHexString (getUnsignedShort (buffer, 2)));
      System.out.println ("4: " + Long.toHexString (getUnsignedInt (buffer, 4)));
   }
}



Tag // ByteBuffer, java

ByteBuffer to String

from Java 2008/09/30 13:18
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("aabcde".getBytes());
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
String s = new String(bytes);

위가 아니라 아래처럼 해야 됩니다. ^^;;

ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("aabcde".getBytes());
byte[] bytes = new byte[buffer.position()];
buffer.flip();       
buffer.get(bytes);
String s = new String(bytes);
System.out.println(s);
1. create a ByteBuffer from a byte array
byte[] bytes = new byte[10];
ByteBuffer buffer = ByteBuffer.wrap(bytes); 
2. retrieve bytes between the position and limit
bytes = new byte[buffer.remaining()];
buffer.get(bytes, 0, bytes.length);
buffer.clear(); 
3. retrieve all bytes in the buffer
bytes = new byte[buffer.capacity()];
buffer.get(bytes, 0, bytes.length);