2010-06-04 4 views
3

나머지 페이로드의 길이에 해당하는 UDP 패킷의 처음 2 바이트 값을 찾으려고합니다. 처음 2 바이트를 알고있는 Java에서이 값을 찾는 가장 좋은 방법은 무엇입니까? java.nio.ByteBuffer은 (는) 사용 하시겠습니까?Java에서 2 바이트의 값을 찾으십시오.

감사

+0

두 개의 8 비트 정수에서 16 비트 정수를 가져 오려고합니까? – zildjohn01

+0

문서에서는 페이로드 길이가 처음 2 바이트임을 명시합니다. 아마도 두 개의 8 비트 정수를 추가하는 대신 단 하나의 16 비트 정수 일 것입니다. – Trevor

+0

간단한 문제에 대한 서사 토론. – Justin

답변

5

내가 보통이 같은 것을 사용 : 내가 int도 있기 때문에 같은 길이를 사용

int length = buildShort(packet.getData()[0], packet.getData()[1]); 

마음 :

static public int buildShort(byte high, byte low) 
{ 
    return ((0xFF & (int) high) * 256) + ((0xFF & (int) low)); 
} 

그런 다음 당신이 당신의 DatagramPacket의 처음 두 바이트를 취할를 short 데이터 유형 (모두로)은 Java로 서명되어 있으므로 더 큰 공간이 필요합니다.

+2

저스틴과 에릭슨의 스타일을 선호합니다. "* 256"및 "|"대신 "<< 8" "+"대신에, 당신이하는 일은 실제로 비트를 이동시키고 결합하는 것입니다. (또한 곱셈과 덧셈으로 해석 될 수 있지만 약간의 의도는 가려 짐). 그건 그렇고, _all_ 정수 형식이 아닌 signed : char! –

+0

예, 연산자는 성능 차이가 없습니다 (JIT는 비트 연산자를 사용하여 비트 연산자를 최적화하는 더러운 작업을 자체적으로 수행합니다). 단지 맛의 문제 일뿐입니다. – Jack

+0

@Dimitris : 글쎄, 나는 동의하지 않습니다. * 실제로 *하는 것은 base-256 인코딩 된 정수를 java 정수로 변환하는 곱셈과 덧셈입니다. 인코딩베이스가 2의 거듭 제곱이라는 것은 운 좋은 우연의 일치입니다. 글쎄, 물론 운이 좋은 것은 아니지만 효율성을 위해 그런 식으로 진행됩니다. 그래서 우리 둘 다 맞을 것 같네요. –

1

ByteBuffer를 사용하는 것은 nio를 사용하여 UDP 패킷을 읽는 경우에만 유용합니다.

static final int getLength(DatagramPacket packet) { 
byte data[] = DatagramPacket.getData(); 
return (int)((0xFF & (int)data[0]) << 8) | (0xFF & (int)data[1])); 
} 
+0

ByteBuffer는 바이트 배열을 크고 작은 엔디안 지원을 포함하여 다양한 종류의 기본 유형으로 해석하는 데 탁월한 지원을 제공합니다. –

+0

사실 여기에 트레이드 오프가 있습니다. ByteBuffer의 할당 비용 (및 후속 가비지 수집)을 데이터 [0], 데이터 [1]에 대한 2 개의 범위 확인 된 메모리 액세스 비용과 비교합니다. ByteBuffer를 DatagramChannel의 소스로 사용하지 않는다면, 나는 그것을 지불하지 않을 것입니다. – Justin

+0

모든'(int)'캐스트는 중복됩니다. 그렇지 않으면 갈 길이 멀다. –

2

당신은 참으로 java.nio.ByteBuffer를 사용할 수있다 : 당신은 유틸리티 메소드를 만들 수 있습니다. 여기에 킥오프 예제 :

ByteBuffer buffer = ByteBuffer.allocate(2); 
buffer.order(ByteOrder.LITTLE_ENDIAN); 
buffer.put(byte1); 
buffer.put(byte2); 
int length = buffer.getShort(0) & 0xFFFF; // Get rid of sign. 
+0

이것은 네트워크와 윈도우 바이트 순서를 전환 할 수있는 능력을 갖지만 객체 할당 (그리고 약간의 추가 로직)을 희생합니다. – Justin

+1

또한 2 바이트 길이를 사용하는 경우 int()로 변환해야합니다. ('((int) buffer.getShort (0)) | 0xFFFF') – Justin

+0

@ Justin : 당신 말이 맞아요. 당신은 부호없는 값으로 끝내고 싶습니다. – BalusC

3

단지 16 비트 값 서명 자바에 의해 트립되지 마십시오 ByteBuffer 편리 사용 :

byte[] data = new byte[MAX_LEN]; 
ByteBuffer buf = ByteBuffer.wrap(data); 
DatagramPacket pkt = new DatagramPacket(data, data.length); 
⋮  
while (connected) { 
    socket.receive(pkt); 
    int len = buf.getShort() & 0xFFFF; 
    ⋮ 
} 

당신이 ByteBuffer를 사용하지 않을 경우를, 변환은 여전히 ​​매우 쉽습니다. 등가 곱셈과 덧셈을 사용할 수 있지만 더 자주 사용되는 비트 연산자를 볼 수 있습니다 :

int len = (data[0] & 0xFF) << 8 | data[1] & 0xFF; 
관련 문제