2013-08-14 3 views
4

MSDN entry for TransmitFile에서 인용 :Win32 TransmitFile()에서 2,147,483,646 바이트 (~ 2 GiB)보다 큰 파일을 어떻게 전송합니까?

전송 작업 기능 2,147,483,646, 32 비트 정수 뺀 최대 바이트 수의 최대 값 인 단일 호출을 사용하여 전송 될 수있는 최대 바이트 단일 호출로 보내기에는 lpTransmitBuffers 매개 변수가 가리키는 파일 데이터의 전후에 전송 된 모든 데이터와 전송할 파일 데이터의 길이에 대한 nNumberOfBytesToWrite 매개 변수에 지정된 값이 포함됩니다. 응용 프로그램이 2,147,483,646 바이트보다 큰 파일을 전송해야하는 경우 각 호출이 2,147,483,646 바이트를 넘지 않으면 서 TransmitFile 함수에 대한 여러 호출을 사용할 수 있습니다. 이 경우, TransmitFile 함수는 파일의 크기를 전송할 바이트 수 값으로 사용하기 때문에 2,147,483,646 바이트보다 큰 파일에 대해 nNumberOfBytesToWrite 매개 변수를 0으로 설정하면 실패합니다.

좋아. TransmitFile로 크기 2*2,147,483,646 bytes (~ 4 GiB)의 파일을 보내는 것은 최소한 두 부분으로 나누어야합니다 (예 : TransmitFile에 대한 두 번의 호출에서 2 GiB + 2 GiB). 그러나 정확히 정확히 어떻게 그 일을하는 동안, 또한 선호 사이에 기본 TCP 연결을 유지하면서?

파일이 실제로 크기 < = 2,147,483,646 바이트

, 하나는 바로 쓸 수있다 :

HANDLE fh = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, 
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 

TransmitFile(SOCK_STREAM_socket, fh, 0, 0, NULL, NULL, TF_DISCONNECT); 

Windows가 처리 할 수 ​​있도록 모든 낮은 수준의 물건 (캐싱, 효율적인 전송을위한 조각으로 데이터를 청크 그러나 비슷한 리눅스와 달리 #syscall과 같이 호출에서 즉시 명백한 오프셋 인수가 없습니다 (비록 다섯 번째 인수 인 LPOVERLAPPED lpOverlapped이 아마도 내가 찾고있는 것 일지 모르지만). 나는 함께 해킹 할 수 있다고 생각하지만, 또한이 물건에 대해 실제로 알고있는 사람으로부터 우아하고 훌륭한 Win32 솔루션을 찾고 있습니다.

되는 OVERLAPPED 구조의 오프셋 및 OffsetHigh 부재를 설정하여 파일 데이터 전송을 시작 16,

는 사용자가 파일 내의 오프셋 (offset)은 64 비트를 지정 lpOverlapped 매개 변수를 사용할 수있다. lpOverlapped가 NULL 포인터이면, 데이터의 전송은 항상 파일의 현재 바이트 오프셋에서 시작됩니다.

그래서 이러한 작업을 수행하는 데 필요한 최소한의 예제가 인터넷 상에 쉽게 제공되지 않기 때문에?

+1

'TF_DISCONNECT' 플래그를 전달하지 않으면 다음 2GB를 보내기 위해'TransmitFile()'을 다시 호출 할 수 있습니다. 'lpOverlapped' 매개 변수는 실제로 파일 오프셋을 제공하는 방법입니다. –

+0

단순히 현재 위치에서 파일을 읽습니다. –

+2

'Socket.SendFile()'시도해 보셨습니까?MSDN은 파일 크기에 대해 아무 말도하지 않기 때문에, 나는 결코 그런 환경을 다루지 않을 것이라고 가정합니다. 'socket.sendFile'은 TransmitFile 함수를 사용하여 작업을 수행합니다. 또한'SetFilePointerEx'를보고'TransmitFile'을 호출하기 전에 파일의 위치를 ​​지정하십시오. –

답변

2

의견에 따라 알아 내기 위해 관리했습니다. LPOVERLAPPED lpOverlapped가 널 포인터 인 경우

그래서, 전화는 (많은 리눅스 sendfile() 콜과 off_t *offset 매개 변수와 같은) 파일의 오프셋 (offset) 현재 파일의 전송을 시작합니다.

#define TRANSMITFILE_MAX ((2<<30) - 1) 

LARGE_INTEGER total_bytes; 
memset(&total_bytes, 0, sizeof(total_bytes)); 

while (total_bytes < filesize) { 
    DWORD bytes = MIN(filesize-total_bytes, TRANSMITFILE_MAX); 
    if (!TransmitFile(SOCK_STREAM_socket, fh, bytes, 0, NULL, NULL, 0)) 
    { /* error handling */ } 

    total_bytes.HighPart += bytes; 
    SetFilePointerEx(fh, total_bytes, NULL, FILE_BEGIN); 
} 

closesocket(SOCK_STREAM_socket); 

이 작업을 수행하는 하나 쓸 수 있도록이 오프셋 (포인터), SetFilePointerEx를 조작 할 수 있습니다. 매우 우아하지는 않지만 작동합니다.

+0

질문이 대답하지 않은 목록에 나타나지 않도록 자신의 대답을 수락해야합니다. –