Delphi Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
델파이 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
FreePascal/Lazarus
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
델마당
볼랜드포럼 광고 모집

델파이 Q&A
Delphi Programming Q&A
[15334] Re:Re:Re: 파일 분할하여 송신하는 법을 알고싶습니다.
눈팅이 [] 3364 읽음    2014-11-13 18:12
음.. 파일분할 송신방법보다는 기본적인 서버 동작방식에대한 고민이 더 필요하실듯합니다.

아래 델파이 서버단 코딩을 보면 한클라이언트에서 요청이들어오면 모든클라이언트에 일방적으로 메세지를 뿌리는데요.. 대강 유추해보면 매니저용 클라이언트에서 먼가 액션을 취하게되면, 나머지 모든 일반 클라이언트들이 먼가 일제히 수신되게끔 구성을하신것 같습니다. 아마도 푸시서버같은 것이겠지요.

문제는 TCP/IP프로토콜로 브로드캐스트를 하려할때 많은 문제가 있다는것입니다. 가장 빈번한 문제로는 모든클라이언트의 연결이 정상적으로 이루어져있는것이 아니라는겁니다. 더군다나 모바일이라면 PC보다 몇십, 몇백배 더 하죠.

예를들면 1000개의 클라이언트가 서버에 물려있다고할때 아래와같은 코딩이라면

1. 0번째 클라이언트부터 연결상 문제가있다면 예외가 발생하게되어 그뒤에 모든 클라이언트들에게는 전송이 안됩니다.
   (예외가 발생하면서 except절을 타게되면서 for문이 종료되서 그렇겠죠? 물론 이문제는 아래와같은 코드로 해결 할 수 있고요..)
             for i:= 0 to IdServer.Socket.ActiveConnections - 1 do
             begin
                try
                  IdServer.Socket.Connections[i].SendText(IntToStr(FileStream.Size) );
                  IdServer.Socket.Connections[i].SendStream(FileStream);
                except
                  {...}
                end;
             end;

2. 1번문제를 위와같이 해결하더라도 연결에 문제가있는 클라이언트마다 예외가 발생하는 시간이 몇십초 이상 걸릴수 있습니다. 문제있는 클라이언트가 100개정도만 있어도 지금보낸 패킷이 몇시간이나 지난뒤에 도착할수도 있습니다.
   (TCP/IP는 상대방에게 제대로 패킷이 전달되었는지를 검증합니다. 만약 특정패킷이 못갔다면 다시시도합니다. 그렇게 여러번 반복하다가 계속안되면 그제야 에러를 토해냅니다.)

3. SendText 나 SendStream을 보낼때 두번날렸다고 반드시 클라이언트에서 2번의 이벤트로 받지는 않습니다.
  예를들어 서버에서 연달아 아래와같이 패킷을 전송했을때
   SendText(a);
   SendText(b);
   따로 a, b 이렇게 들어올때도있지만 ab이렇게 같이 들어올때도 있습니다.

위 문제외에도 더 많은 문제들이있습니다.

TCP/IP의 기본 통신방식은 클라이언트 요청이 있어야만 서버가 응답을합니다. 이렇게 해야 가장 안전 할 수 있습니다.
이 베이스로 로직을 다시 생각해 보시기 바랍니다.

그리고 질문하신 파일분할 송수신 방법에대한것은 위의 기본통신방식이 지켜지면 자연스레 여러방법이 나옵니다.

혹 파일이 1M이상되어 스택오버플로 에러때문에 오류가 나는것이라면 파일자체를 분리해서 저장을 해야겠죠.
(쓰레드당 스택은 기본 1M입니다.)

전송프로세스는 아래와같은 방식으로 하면 될것이구요..
클라이언트 요청( 무언가 받을것이있는지) -> 서버 응답(파일있음, 전체파일크기, 파일수) -> 클라이언트요청(파일1) -> 서버 응답(전송하는파일크기, 스트림) -> 클라이언트요청(파일2) -> 서버 응답(전송하는파일크기, 스트림)...클라이언트요청(마지막파일) -> 서버 응답(전송하는파일크기, 스트림) -> 클라이언트 파일합침

다만 저라면 위와같이 서버단에서 파일전송을 하기보다는 HTTP서버를 통해 클라이언트에서 파일을 받을것을 택하겠습니다.
즉 델파이로 만든 서버에서는 받야야할 파일의 URL정도만 클라이언트에게 보내주고, 클라이언트는 해당 URL을가지고 HTTP통신으로 다운로드 받습니다.




Jinzeros 님이 쓰신 글 :
: 네 감사합니다. 수정하였고요.
: 근데 하나더 질문이있는데...
:
: Delphi에서 file을 분할해서 보내고싶은데 어떻게보내는지 알고싶습니다.
: ㅠ
:
: 눈팅이 님이 쓰신 글 :
: : 일단 실제 FileSocket에서 수신이 안되는것이 확실한가요?
: : 자바소스를 봤을때는 특정부분에 예외가 발생하면 발생하면 수신이 제대로 되었는지조차 확인이 안될것같은데요..?
: :
: : 일단 아래와같이 처리를 해주셔야 예외가 발생했을때 무엇때문인지라도 확인이 가능하겠지요?
: :
: : 변수 선언 또는 생성코드들...
: : try {
: :     자바코드들...
: : } catch(Exception e) {
: :     Log.i(e.ToString());
: : } finally {
: :     각종해제코드들...
: : }
: :
: : 그리고 String fName = dis.readUTF(); 이구문이 파일생성시 파일명을 넣어주는부분인것같은데
: : readUTF() 메소드를 통해서 해당변수에 파일이름이 아닌 데이터자체를 넣고있네요...
: : 스트림의 내용에따라 파일명규칙위반 문자가들어 오면 File f = new File(fName); 위치에서 예외가 발생하겠죠?
: :
: : 참고로 안드로이드에서 파일을 저장시 기본적으로 앱에서만 사용할 수 있는 내부스토리지에 저장이됩니다. 혹시
: : 위 데이터자체 내용이 파일의 이름을 나타내는것이었고, 그경로가 외부스토리지 경로라면 manifest에서 설정을 추가해줘야합니다.
: :
: : ※ 아, 그리고 델파이쪽 코드도 FileStream.Free; 구문이 예외상황이 없으면 해제되는 일은 없겠네요..
: :
: :
: :
: : Jinzeros 님이 쓰신 글 :
: : : 내용은 제목과 같이 델파이에서 보낸파일을 안드로이드에서 수신하는 프로그램입니다.
: : :
: : : 안드로이드 ... 즉, 자바는 처음하는데... 잘모르겟습니다;;
: : :
: : : 고수님들 부탁드립니다. ㅠ 참고로 Client에서 Server에 접속은 됩니다. 메시지 송수신은 잘됩니다.
: : :
: : : 파일이랑 스트링 분리하라고 인터넷에서 본것같아 2개를 분리해뒀습니다.
: : :
: : : File 송수신 FileSocket 수신이 안됨.(연결은 되어있음)
: : :
: : : 메시지 송수신 MsgSocket  정상적으로 잘됨.(아래 소스에는 없습니다.)
: : :
: : : # delphi 7   ServerSocket
: : : =========================================================================
: : :          sFileName := 'c:\sample.bmp';
: : :          try
: : : //            FileStream := TFileStream.Create(sFileName, fmOpenRead);
: : :             FileStream := TFileStream.Create(sFileName, fmOpenRead or fmShareDenyWrite);
: : :
: : :             FileStream.Position := 0;
: : :       // Add the length of the data, so the client will know how much data to expect.
: : :       // Append #0 so it can determine where the size info stops.
: : :             for i:= 0 to IdServer.Socket.ActiveConnections - 1 do
: : :             begin
: : :                IdServer.Socket.Connections[i].SendText(IntToStr(FileStream.Size) );
: : :                IdServer.Socket.Connections[i].SendStream(FileStream);
: : :             end;
: : :          except
: : :             FileStream.Free;
: : :          end;
: : : =========================================================================
: : :
: : : # Android  ClientSocket
: : : =========================================================================
: : :                     DataInputStream dis = new DataInputStream(fileRecevSocket.getInputStream());
: : :                     Log.i("tree","********************");
: : :                
: : :                
: : :                     Log.i("tree","***AAAAAAAAAAAAAAAA***");                   
: : :                     String fName = dis.readUTF();
: : :                     Log.i("tree","파일명 :" + fName + "을 전송 받았습니다.");
: : :                     fName = fName.replaceAll("a", "b");
: : :                     // 파일을 생성하고 파일에 대한 출력 스트림 생성
: : :                     File f = new File(fName);
: : :                     fos = new FileOutputStream(f);
: : :                     bos = new BufferedOutputStream(fos);
: : :                     Log.i("tree","파일명 :" + fName + "파일을 생성하였습니다.");
: : :
: : :                     //바이트 데이터를 전송받으면서 기록
: : :                     int len;
: : :                     int size = 4096;
: : :                     byte[] data = new byte[size];
: : :                     while ((len = dis.read(data)) != -1)
: : :                     {
: : :                         bos.write(data, 0, len);
: : :                     }
: : :    
: : :                     bos.flush();
: : :                     bos.close();
: : :                     fos.close();
: : :                     dis.close();
: : :                     Log.i("tree","파일 수신 작업을 완료하였씁니다.");
: : :                     Log.i("tree","받은 파일의 "
: : :                             + ""
: : :                             + "사이즈 : " + f.length());
: : : =========================================================================

+ -

관련 글 리스트
15328 델파이에서 보낸 파일을 안드로이드에서 수신 하는 프로그램짜고있습니다. Jinzeros 2193 2014/11/07
15329     Re:델파이에서 보낸 파일을 안드로이드에서 수신 하는 프로그램짜고있습니다. 눈팅이 2385 2014/11/10
15332         Re:Re: 파일 분할하여 송신하는 법을 알고싶습니다. Jinzeros 2017 2014/11/12
15334             Re:Re:Re: 파일 분할하여 송신하는 법을 알고싶습니다. 눈팅이 3364 2014/11/13
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.