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도 패킷이 손실되나요??
  • 2017년 12월 06일에 작성됨

조회수 65


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() 에서 예외가 발생할 것입니다.

  • 2017년 12월 07일에 작성됨

로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close