자바(Java)를 사용해서 개발한 서비스나 애플리케이션에서 C/C++로 개발된 서버에 연결해서 데이터를 전송하거나 수신하는 경우에 unsigned로 인해서 통신에 불편함이 발생하게 된다. 그래서 이런 문제를 쉽게 해결하기 위해서 구글에서는 프로토콜 버퍼(https://developers.google.com/protocol-buffers/), 스리프트(페이스북에서 개발해서 아파치에 기증, https://thrift.apache.org/)와 같은 직렬화 라이브러리를 많이 사용하고 있다.
그래도 이런 직렬화 라이브러리를 사용하지 않고, unsigned 타입을 프로토콜로 사용하는 서버와 통신하기 위해서 unsigned를 처리하는 자바 클래스 몇 개를 살펴보자. 아래 클래스는 1, 2, 4 byte의 배열을 읽어서 2, 4, 8 byte의 데이터 타입으로 사용하고, 2, 4, 8 byte를 unsigned 1, 2, 4 byte로 변경하는 코드이다.
1. UnsignedByte
public class UnsignedByte { public static short parse( byte[] data, int offset ) { return (short)(data[offset] & 0xff); } public static short parse( byte[] data ) { return parse( data, 0 ); } public static byte[] parse( short number ) { return new byte[] { (byte)(number & 0xff) }; } }
2. UnsignedShort
public class UnsignedShort { public static int parse( byte[] data ) { return parse( data, 0 ); } public static int parse( byte[] data, int offset ) { return ((data[offset] & 0xff) << 8) | (data[offset+1] & 0xff); } public static byte[] parse( int number ) { byte[] data = new byte[2]; data[0] = (byte)((number >> 8) & 0xff); data[1] = (byte)(number & 0xff); return data; } }
3. UnsignedInt
public class UnsignedInt { public static long parse( byte[] data ) { return parse( data, 0 ); } public static long parse( byte[] data, int offset ) { return (((long) data[offset] & 0xffL) << 24) | (((long) data[offset+1] & 0xffL) << 16) | (((long) data[offset+2] & 0xffL) << 8) | ((long) data[offset+3] & 0xffL); } public static byte[] parse( long number ) { byte[] data = new byte[4]; data[0] = (byte) ((number >> 24) & 0xff); data[1] = (byte) ((number >> 16) & 0xff); data[2] = (byte) ((number >> 8) & 0xff); data[3] = (byte) (number & 0xff); return data; } }
* Reference
– https://github.com/ryantenney/oscar