개발/Java

[java] DataInputStream.read(byte[] b)와 ByteArrayOutputStream.write(byte[] b)의 b

승리승리 2021. 7. 1. 22:42

#목적
   1. java Socket통신 후 Response Data 처리 과정에서 오류가 발생하였고 InputStream의 read와 OutputStream의 write를 짚고 넘어가고자 작성한다.
      a. 간헐적으로 HexString의 일부를 읽지 못하고 다른 일부는 0으로 채워지는 현상이 발생하였다.
      b. 안될거면 처음부터 안돼야지 왜 대부분 잘되다가 가끔 발생하지?
      c. 다른 기관과 통신을 태울때는 대부분 안되다가 가끔 잘되었다. 

#내용
   1. 흐름은 아래와 같다.
      a. 인증기관으로 Request Data 전송
      b. 인증기관으로부터 4Byte를 읽어들임 (header이며 body의 길이를 나타냄)

DataInputStream dataInputStream = new DataInputStream(inputStream);
byte[] bodyByteArray = null;
byte[] headerBuffer = new byte[4];
dataInputStream.read(headerBuffer);

 

      c. 인증기관으로부터 body의 길이만큼 body를 읽어들임

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] bodyByteArray = new byte[bodyLen];
while ((readInt = dataInputStream.read(bodyByteArray, 0, bodyByteArray.length)) != -1) {
    byteArrayOutputStream.write(bodyByteArray, 0, readInt);
    bodyLen = bodyLen - readInt;
    if (bodyLen <= 0) {
        break;
    }
}

 

      d. 읽어들인 값을 Hex String으로 변환

String readDataHexStr = UCPIDUtil.byteArrayToHexString(bodyByteArray);

public static String byteArrayToHexString(byte[] bytes){
    StringBuilder sb = new StringBuilder();
    for(byte b : bytes){
        sb.append(String.format("%02X", b&0xff));
    }
    return sb.toString();
}

 

   2. 인증기관 측에 전송한 Response Data를 요청
      a. 정상 Data확인
   3. WireShark를 사용하여 패킷 분석
      a. 정상 처리된 경우와 비교해보니 문제가 없다고 판단
   4. java socket통신 관련 내용을 찾아보던 중 ByteArrayOutputStream객체에서 toByteArray()함수 호출을 발견
   5. 아래와 같이 수정 하여 HexString생성 후 약 5천번 Test를 진행 및 정상 동작 확인

String readDataHexStr = Util.byteArrayToHexString(byteArrayOutputStream.toByteArray());

 

   6. 결론은 ByteArrayOutputStream.write(byte[] b, int off, int len)의 결과 값 사용이 잘못 되었다.
나는 아래 코드를 통해 인증기관의 Response Data를 body의 길이 만큼 읽어 들였다.

while ((readInt = dataInputStream.read(bodyByteArray, 0, bodyByteArray.length)) != -1) {

이때 readInt값은 [버퍼에 읽힌 바이트의 수] 이다.
디버깅 시 가끔 readInt값이 bodyByteArray.length값 보다 작을 경우가 존재하였다.
이에 그 차이만큼 0이 채워지고 원하는 Response값을 얻지 못하였다.
이를 위해 ByteArrayOutputStream에 Read한 값을 계속해서 쓰고 마지막에 ByteArrayOutputStream에 저장된 모든 값을 Byte배열로 변환하여 사용하였다.

#배운점
   1. Data의 형식을 어림짐작하지 말고 정확히 파악하고 사용해야겠다.

 

 

'개발 > Java' 카테고리의 다른 글

Reactive란  (0) 2022.01.21
[java] dual pivot quick sort/정렬  (0) 2021.08.11
[java] JSON null check  (0) 2021.06.13
[java] switch-case 문자열 조건  (0) 2021.04.19
[java] Generic을 사용해 Class 및 Method 동적 생성 및 호출  (0) 2021.04.18