저번에 네트워크 코딩 관련해서 조언을 구한 뉴비입니다.
조언해주신것을 바탕으로 파이썬과 소켓으로 코드를 짰습니다. 그런데 문제가 생겼는데, 크기가 작은 파일을 전송할경우는 괜찮은데 몇백메가를 넘어서는 파일의 경우 원래 크기보다 작게 수신을 합니다.
송신하는 서버와 수신하는 클라가 1024바이트씩 송수신하면서 파일의 크기만큼 루프를 도는 식으로 파일을 전송하였습니다. sendall()과 recv()함수를 사용했구요.
뭐가 문제인지 확인하기 위해 마지막 송수신에서 바이트내용을 출력하니 루프는 같은 횟수 돌았지만, 전혀 다른 내용이더라구요. 수신이나 송신할때 일부 유실되는 데이터가 있는지 싶어서 두가지 방법으로 해봤습니다.
1. [기존방식] 파일크기를 읽어와서 파일 크기만큼 루프돌며 전송과 수신 => 전부 보냈는지는 모르겠지만 확실히 덜 받아왔음. 원본보다 파일 크기가 작음.
2. 1024바이트씩 수신하면서 1024보다 작게 받아지는경우마다 멈춰서 얼마나 받아왔나 확인함 => 작은경우도 많고 얼마나 작게 받는지도 불규칙적이라 마지막 파일 데이터인지 확인이 불가함. => 파일의 바이너리가 공백일경우 공백으로 받아서 수신이 불규칙적 혹은 소켓에서 데이터 유실을 예상.
두가지 방법 모두 했지만 결국 실패했네요. 구글링해보니 send()는 저수준 네트워크 함수라 데이터가 유실되는 경유가 있으니 고수준 함수인 sendall()을 사용하라해서 seneall을 사용하였지만, 그대로네요...
혹시 이에대해 아시는 분 있나요..?
그리고 혹시 여유있으시거나 코드를 확인해봐야겠다하시는 분있으시면 아래 링크에 있어요..
너무 긴 질문이라 죄송합니다.. :<
- dc official App
루프백으로 테스트하시는거고 TCP프로토콜이라면 입출력계층에서 데이터가 유실될 가능성은 거의 없어요 - dc App
프로그램상에서 입출력 & 직렬화-역직렬화 작업 수행 중 흘리고 있을 가능성이 큽니다. - dc App
recv는 어떻게 돌고 있나요? recv는 원칙적으론 지시한 사이즈보다 적게 받을수도 있습니다. 그렇기 때문에 패킷으로부터 받은 내용을 별도의 버퍼에 적재해서 지시한 사이즈만큼 쌓일 때까지 루프를 돌아야 합니다 - dc App
조언감사해요! 전송을 위한 파일의 직렬화는 with open('file', 'rb') as f: socket.sendall(f.read(1024))를 통해 직렬화후 전송합니다. recv루프는 사전에 getsize를 통해 알아낸 파일크기 정수를 수신한 후, recv(1024)씩 받아냅니다. - dc App
이 댓글은 게시물 작성자가 삭제하였습니다.
recv 실행됬으면 1024바이트만큼 데이터가 들어왔다고 가정하여 루프를 돕니다. 아마 지적해주신 부분이 맞다면 이것이 잘못된거같네요. 그렇다면 실제로 받아낸 데이터의 크기를 매번 확인해야하는데, 말씀해주신 버퍼라는 것을 이용하면 되나요? 버퍼에 대해서 잘몰라서요.. - dc App
아 버퍼는 그냥 직렬화된 데이터를 완전히 받을 때까지 선형 데이터로 저장하기 위한 자료 공간이에요. 추상적인거고 벡터 리스트 배열 등 필요한 자료구조를 이용하면 되요 - dc App
아아! 알겠습니다. 조언 감사해요ㅠㅠ 코드 고쳐보겠습니다. - dc App
아마 파이썬 소켓 패키지는 recv 반환 결과로 직렬 데이터의 rvalue가 나와서 그걸 변수에 받아 저장할거에요. 이걸 다른 바이트열 객체에 연결하면서 실제 내가 받은 데이터의 길이를 카운트하시고 원하시는 파일 사이즈만큼 데이터를 받을 때까지 recv를 반복하시고 이후 바이트열 객체에 모인 내용을 파일에 쓰시면 될 것 같습니다 - dc App
네 :) - dc App