java tcp 파일송수신이 잘안되요

전송측에서 bis = new BufferedInputStream 으로 만들어서 data = 4096 while (len = bis.read(data)) != -1) dos.write(data, 0, len); 요렇게 날리고있습니다

len값은 보낼때 일정하게 4096으로 잘가는데요

받는측에서 while ((len = dis.read(data)) != -1) 으로 읽는데 파일이 제대로 안오길래 len값 찍어보니 아래와같이 나오네요;;; 왜이러죠? udp도 아니고 2번째 보낼때도 len값은 4096으로 받았어야할텐데 ;;; 몇바이트 안되는 텍스트파일은 무리없이 잘받아집니다.

이미지

/

이렇게 받아져서그런지... 132kb파일을 보내는데 카운트27에서 멈춥니다..

어떻게 해야할까요?

  • 공인서버말고 같은nat밑의 사설ip로 서버를 테스트했더니 갑자기 잘받아지네요;;;
  • 공인서버쪽 문제인걸까요 아님 tcp도 패킷이 손실되나요??

1답변

  • 일단 read(byte[]) 를 보시면 아래와 같은 내용이 있습니다.

    If the length of b is zero, then no bytes are read and 0 is returned; otherwise, there is an attempt to read at least one byte. 
    

    read() 을 호출하면 적어도 한바이트를 읽는 것을 보장하지만 전송한 곳의 데이터를 한번에 다 읽을 수 있다고 서술되어 있지 않습니다. 즉, 보낸 쪽에서 4096 바이트를 전송하고 받는 쪽에서 read() 를 호출 한다고 해도 4096 바이트를 한번에 받지 못할 수 있습니다.

    무엇 보다 TCP 통신은 데이터의 전송 순서와 데이터의 무결성을 유지를 보장하지, 한번에 모든 데이터를 보내는 것을 보장하지 않습니다.

    보내려는 데이터들은 TCP 에서 세그먼트로 나뉘어서 전송이 되고 수신지의 버퍼에 쌓이게 됩니다. read() 는 이 버퍼에 쌓인 데이터를 읽어 오는데 상대 쪽에서 전송한 모든 데이터가 버퍼에 쌓이지 않았다면 쌓인 부분까지만 읽어오고 나머지는 다음 read() 호출에서 읽어오게 됩니다.

    즉, 4096 바이트를 보낸다 하여도 시스템의 상황/네트워크의 상황/데이터의 크기/MTU 등 에 따라 조각이 나서 전송이 됩니다.

    이러한 이유로 말씀하신 크기인 14202676 과 같이 데이터가 쪼개져서 읽히는 것을 볼 수 있습니다.

    따라서 read() 로 보낸 데이터를 한번에 받을 수 있을 거란 생각을 하면 안됩니다. 132KB 를 수신할 계획이면 아래와 같이 작성해 보세요.

    byte[] data = new byte[132 * 1024];
    
    int len = 0;
    do {
        int read = dis.read(data, len, data.length - len);
        if (read == -1)
               break;
        len += read;
    } while (len != data.length);
    
    if (len != data.length)
        throw new RuntimeException("fails");
    

    수신한 데이터의 값이 132KB 에 못 미치는 것은 좀더 자세한 코드가 필요할 듯싶습니다. 올려주신 코드만으로는 판단하기 가 어렵네요.


    공인서버말고 같은nat밑의 사설ip로 서버를 테스트했더니 갑자기 잘받아지네요;;;

    네트워크가 같은 망이냐 아니냐에 따라서 그만큼 통신 지연이 발생할 수 있습니다. 이로 인해서 read() 시점에 버퍼에 4096 바이트의 데이터가 있을 수 도 있고 없을 수 도 있습니다.

    같은 망일 경우 지연이 적으니 read() 시점에 4096 바이트가 있을 확률이 높기 때문에 말씀하신 상황에서 잘 동작하고 다른 망에 있는 서버는 그만큼 확률이 낮기 때문에 잘 동작하지 않는 것처럼 보이는 듯 합니다.

    공인서버쪽 문제인걸까요 아님 tcp도 패킷이 손실되나요??

    TCP 는 통신 중 데이터가 손실되면 이를 복구하기 위해서 여러가지 작업을 합니다. 만약 이 작업을 통해서도 복구를 할 수 없다면 read() 에서 예외가 발생할 것입니다.

ᕕ( ᐛ )ᕗ
로그인이 필요합니다

작성한 답변에 다른 개발자들이 댓글을 작성하거나 댓글에 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.