Передача файлов с помощью TransmitFile

Функция TransmitFile служит для быстрой передачи данных из файлов, благодаря тому, что она работает
в режиме ядра(kernel mode), и не происходят частые переключения между режимами. Данная функция это
дополнение к WinSock, то есть если Вы пишите программу для Win32 и после хотите перенести код на
Unix-системы, то придется значительно изменять код. Плюсом функции является то, что программисту
не приходится заботиться о правильном чтении и отправки данных, всю работу возлагает на себя
WinSock2. Определение функции:

BOOL TransmitFile(
SOCKET hSocket,
HANDLE hFile,
DWORD nNumberOfBytesToWrite,
DWORD nNumberOfBytesPerSend,
LPOVERLAPPED lpOverlapped,
LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
DWORD dwFlags
);

Параметры:

hSocket – подключенный сокет, через который будет иди передача данных, тип сокета должен быть
ориентированным на соединение. TransmitFile не поддерживает UDP сокеты;
hFile – описатель открытого файла, данные которого будут передаваться;
nNumberOfBytesToWrite – количество записываемых из файла байт, если 0 то отправляется файл целеком;
nNumberOfBytesPerSend – размер блоков данных для операции записи, если 2048 то передаче будет идти
блоками по 2 килобайта, если 0 то размер блоков устанавливается по умолчанию;
lpOverlapped – определяет структуру OVERLAPPED, для перекрытого ввода/вывода;
lpTransmitBuffers – представляет структуру TRANSMIT_FILE_BUFFERS, содержащую информацию, которая
передается до и после отправки данных из файла:

typedef struct _TRANSMIT_FILE_BUFFERS {
PVOID Head;
DWORD HeadLength;
PVOID Tail;
DWORD TailLength;
} TRANSMIT_FILE_BUFFERS;

Head – указатель на данные которые передаются до отправки;
HeadLength – количество передаваемой информации;
Tail – указатель на данные которые передаются после отправки;
TailLength - количество передаваемой информации.
dwFlags – флаги для управления работой TransmitFile:
TF_DISCONNECT – закрыть сокет после передачи;
TF_REUSE_SOCKET – использовать сокет для повторной передачи;
TF_USE_DEFAULT_WORKER, TF_USE_SYSTEM_THREAD – передача должна идти в контексте системного процесса,
используются при передаче больших файлов;
TF_USE_KERNEL_APC – передача будет идти при помощи асинхронных вызовов процедур(APC), используется
если нужна лишь одна процедура чтения;
TF_WRITE_BEHIND – завершить работу без подтверждения о приеме данных.

Для демонстрации работы функции создано тестовое приложение на MFC, которое всю принимаемую
информацию будет выводить на экран, исходник приложения находится в архиве к данной статье.
Теперь код программы передачи файлов:

#include <Winsock2.h>//ws2_32.lib
#include <Mswsock.h>//Mswsock.lib
#include <windows.h>
#include <iostream.h>
#include <conio.h>

int main()
{
SOCKET sTransmit;
SOCKADDR_IN InetAddr;
HANDLE hFile;
WSADATA wsaData;
if(!WSAStartup(0x0202,&wsaData))
{
if((sTransmit = socket(AF_INET,SOCK_STREAM,0)) != INVALID_SOCKET)
{
InetAddr.sin_family = AF_INET;
InetAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//htonl(INADDR_ANY);
InetAddr.sin_port = htons(4004);
if(connect(sTransmit,(struct sockaddr *)&InetAddr,sizeof(InetAddr)) != SOCKET_ERROR)
{
hFile=CreateFile(
"---.cpp",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
BOOL bResult = TransmitFile(sTransmit,hFile,0
/*целеком*/,1024,NULL,0,TF_DISCONNECT);
if(!bResult){cout<<"Error TransmitFile"<<endl;}
}
else{cout<<"Error CreateFile"<<endl;}
}
else{cout<<"Error connect"<<endl;}
}
else{cout<<"Error socket"<<endl;}
}
else{cout<<"Error WSAStartup"<<endl;}
CloseHandle(hFile);
if(closesocket(sTransmit)==SOCKET_ERROR){cout<<"Error closesocket"<<endl;}
WSACleanup();
cout<<"Press any key to continue"<<endl;
while (!_getch());
return 0;
}

 
« Предыдущая статья   Следующая статья »