Функция 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; }
|