|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - [решено] Реализация обновления программы - ClientSocket и ClientServer |
|
|
C/C++ - [решено] Реализация обновления программы - ClientSocket и ClientServer
|
Будем жить, Маэстро... Сообщения: 6694 |
Профиль | Сайт | Отправить PM | Цитировать
Привет. Заранее приношу извинение если буду использовать неверную терминологию, но до недавнего времени у меня небыло необходимости в использовании этих компонентов и самой технологии. Задача в общем-то такова, есть клиет-программа, на сервере есть обновления к этой программе, нужно по нажатию на кнопку\пункт меню "Обновить", чтобы программа скачала только те модули, которые новее тех, которые присутствуют рядом с программой. Аналог такого обновления, любой антивирус или AVZ. Поискал в сети, нашёл статью - Передача файлов в C++Builder через TClientSocket и TServerSocket. По примеру сделал тестовую программу, в рамках одного компьютера она работает, но там, в примере, есть клиентская часть и серверная.
Вот представьте, что наше обновление - этот файл - QuickKiller_2.20.7z нужно скачать и находится он здесь - http://tools.oszone.net/Drongo/QuickKiller_2.20.7z. Но скачивать нужно как обновление (как менеджер закачек), а не через диалоговое окно "Сохранить файл". Архив простенького проекта прикрепил, собирал по примеру выше, при нажатии на кнопку "Скачать" устанавливает соединение и на этом всё. Собственно, я не знаю в какую сторону смотреть и те ли компоненты, которые я выбрал, нужны для этих целей? Среда разработки Цитата:
|
||
------- Отправлено: 20:43, 14-04-2010 |
Старожил Сообщения: 232
|
Профиль | Сайт | Отправить PM | Цитировать ClientSocket работает на низком уровне (т.е напрямую по TCP), а файлик лежит в WEB. Думаю нужно использовать библиотеку WinInet.
Вот кусок кода осуществляющий скачку с Web используя WinInet DWORD WINAPI DownloadThread(LPVOID lpParam) { DOWNLOAD_DATA data = *(DOWNLOAD_DATA *)lpParam; HINTERNET hInetSession; HINTERNET hInetFile; HANDLE hFile; OVERLAPPED ovlp; DWORD dwOffset = 0; DWORD dwRead; TCHAR ReadBuf[4*1024]; lstrcpy((LPTSTR)&data, NULL); hInetSession = InternetOpen("Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR 1.0.2914)", PRE_CONFIG_INTERNET_ACCESS, NULL, NULL, 0); if(hInetSession == NULL) { WritePrivateProfileString(data.FileName, "URL", data.Url, IniFile); data.sock->SendFormatText(0, "INET_OPEN_ERROR\r\n%li", GetLastError()); return -1; } hInetFile = InternetOpenUrl(hInetSession, data.Url, NULL, 0, 0, NULL); if(hInetFile == NULL) { WritePrivateProfileString(data.FileName, "URL", data.Url, IniFile); data.sock->SendFormatText(0, "INET_OPEN_URL_ERROR\r\n%li", GetLastError()); return -1; } hFile = CreateFile(data.FullFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if(BAD_HANDLE(hFile)) { data.sock->SendFormatText(0, "SAVE_FILE_OPEN_ERROR\r\n%li", GetLastError()); InternetCloseHandle(hInetSession); InternetCloseHandle(hInetFile); return -1; } if(data.dwOffset == 1) InternetSetFilePointer(hInetFile, GetFileSize(hFile, NULL), NULL, FILE_BEGIN, 0); data.sock->SendFormatText(0, "DOWNLOAD_BEGIN\r\n%s", data.FileName); do { InternetReadFile(hInetFile, ReadBuf, sizeof(ReadBuf), &dwRead); if(dwRead >= 0) { ovlp.hEvent = NULL; ovlp.OffsetHigh = NULL; ovlp.Offset = GetFileSize(hFile, NULL); WriteFile(hFile, ReadBuf, dwRead, NULL, &ovlp); dwOffset += dwRead; } else { InternetCloseHandle(hInetSession); InternetCloseHandle(hInetFile); hInetSession = InternetOpen("Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR 1.0.2914)", PRE_CONFIG_INTERNET_ACCESS, NULL, NULL, 0); if(hInetSession == NULL) { WritePrivateProfileString(data.FileName, "URL", data.Url, IniFile); data.sock->SendFormatText(0, "INET_OPEN_ERROR\r\n%li", GetLastError()); CloseHandle(hFile); return -1; } hInetFile = InternetOpenUrl(hInetSession, data.Url, NULL, 0, 0, NULL); if(hInetFile == NULL) { WritePrivateProfileString(data.FileName, "URL", data.Url, IniFile); data.sock->SendFormatText(0, "INET_OPEN_URL_ERROR\r\n%li", GetLastError()); CloseHandle(hFile); InternetCloseHandle(hInetSession); return -1; } InternetSetFilePointer(hInetFile, dwOffset, NULL, FILE_BEGIN, NULL); } } while(dwRead); CloseHandle(hFile); InternetCloseHandle(hInetSession); InternetCloseHandle(hInetFile); data.sock->SendFormatText(0, "DOWNLOAD_END\r\n%s", data.FileName); return 1; } |
------- Отправлено: 00:19, 15-04-2010 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Будем жить, Маэстро... Сообщения: 6694
|
Профиль | Сайт | Отправить PM | Цитировать ganselo, спасибо, но если можно подробнее, куда и как этот код нужно подставить? Я не понимаю.
|
------- Отправлено: 12:32, 15-04-2010 | #3 |
Старожил Сообщения: 232
|
Профиль | Сайт | Отправить PM | Цитировать Drongo, я этот код выдернул из своего примитивного менеджера закачек.
Вот код с комментами: struct DOWNLOAD_DATA { char Url[1024]; //ссылка на файл BOOL bFlag; // если TRUE, то осуществляется докачка }; //закачку я осуществлял в отдельном потоке. DWORD WINAPI DownloadThread(LPVOID lpParam) { DOWNLOAD_DATA data = *(DOWNLOAD_DATA *)lpParam; HINTERNET hInetSession; HINTERNET hInetFile; HANDLE hFile; OVERLAPPED ovlp; DWORD dwOffset = 0; DWORD dwRead; TCHAR ReadBuf[4*1024]; hInetSession = InternetOpen("Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR 1.0.2914)", PRE_CONFIG_INTERNET_ACCESS, NULL, NULL, 0); //Возвращает хэндл сессии if(hInetSession == NULL) //тут всё понятно { return -1; } hInetFile = InternetOpenUrl(hInetSession, data.Url, NULL, 0, 0, NULL); //по сути открываем файл if(hInetFile == NULL) //снова проверяем { return -1; } hFile = CreateFile(data.FullFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); //открываем файл для сохранения if(hFile == INVALID_HANDLE_VALUE) //проверяем { InternetCloseHandle(hInetSession); //закрываем сессию InternetCloseHandle(hInetFile); //закрываем файл return -1; } if(data.bFlag) //осуществляется докачка InternetSetFilePointer(hInetFile, GetFileSize(hFile, NULL), NULL, FILE_BEGIN, 0); //сдвигаем чтение на GetFileSize бит //начинаем скачку do { InternetReadFile(hInetFile, ReadBuf, sizeof(ReadBuf), &dwRead); //читаем в буффер if(dwRead >= 0) //если считали { ovlp.hEvent = NULL; ovlp.OffsetHigh = NULL; ovlp.Offset = GetFileSize(hFile, NULL); WriteFile(hFile, ReadBuf, dwRead, NULL, &ovlp); //пишем в наш файл dwOffset += dwRead; } else //не считали, пытаемся повторить скачивание { InternetCloseHandle(hInetSession); //закрываем сессию InternetCloseHandle(hInetFile); //закрываем удалённый файл hInetSession = InternetOpen("Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR 1.0.2914)", PRE_CONFIG_INTERNET_ACCESS, NULL, NULL, 0);//пытаемся повторить скачку if(hInetSession == NULL) { CloseHandle(hFile); return -1; } hInetFile = InternetOpenUrl(hInetSession, data.Url, NULL, 0, 0, NULL); if(hInetFile == NULL) { CloseHandle(hFile); InternetCloseHandle(hInetSession); return -1; } InternetSetFilePointer(hInetFile, dwOffset, NULL, FILE_BEGIN, NULL); } } while(dwRead); //закрываем всё лишнее CloseHandle(hFile); InternetCloseHandle(hInetSession); InternetCloseHandle(hInetFile); return 1; } |
------- Отправлено: 15:24, 15-04-2010 | #4 |
Будем жить, Маэстро... Сообщения: 6694
|
Профиль | Сайт | Отправить PM | Цитировать ganselo, То что есть комментарии это хорошо, но как правильно эту функцию объявить? Как функцию вызвать? Откуда?
Цитата Drongo:
|
||
------- Отправлено: 16:15, 15-04-2010 | #5 |
Старожил Сообщения: 232
|
Профиль | Сайт | Отправить PM | Цитировать void __fastcall TForm1::UpdateClick(TObject *Sender) { HANDLE hThread; DOWNLOAD_DATA data; strcpy(data.Url, "ссылка на файл"); data.bFlag = false; hThread = CreateThread(NULL, 0, DownloadThread, &data, 0, NULL); if(hThread == INVALID_HANDLE_VALUE) { ShowMessage("Error. Can't create thread!"); return; } CloseHandle(hThread); } //--------------------------------------------------------------------------- |
------- Отправлено: 19:15, 15-04-2010 | #6 |
Будем жить, Маэстро... Сообщения: 6694
|
Профиль | Сайт | Отправить PM | Цитировать ganselo, Вот такая ошибка компоновщика получается.
Цитата:
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "ClientSocket1.h" #include <WinInet.h> //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; struct DOWNLOAD_DATA { char Url[1024]; //ссылка на файл BOOL bFlag; // если TRUE, то осуществляется докачка }; //закачку я осуществлял в отдельном потоке. DWORD WINAPI DownloadThread(LPVOID lpParam) { DOWNLOAD_DATA data = *(DOWNLOAD_DATA *)lpParam; HINTERNET hInetSession; HINTERNET hInetFile; HANDLE hFile; OVERLAPPED ovlp; DWORD dwOffset = 0; DWORD dwRead; TCHAR ReadBuf[4*1024]; hInetSession = InternetOpen("Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR 1.0.2914)", PRE_CONFIG_INTERNET_ACCESS, NULL, NULL, 0); //Возвращает хэндл сессии if(hInetSession == NULL){ //тут всё понятно return -1; } hInetFile = InternetOpenUrl(hInetSession, data.Url, NULL, 0, 0, NULL); //по сути открываем файл if(hInetFile == NULL){ //снова проверяем return -1; } hFile = CreateFile(data.Url, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); //открываем файл для сохранения if(hFile == INVALID_HANDLE_VALUE){ //проверяем InternetCloseHandle(hInetSession); //закрываем сессию InternetCloseHandle(hInetFile); //закрываем файл return -1; } if(data.bFlag) //осуществляется докачка InternetSetFilePointer(hInetFile, GetFileSize(hFile, NULL), NULL, FILE_BEGIN, 0); //сдвигаем чтение на GetFileSize бит //начинаем скачку do{ InternetReadFile(hInetFile, ReadBuf, sizeof(ReadBuf), &dwRead); //читаем в буффер if(dwRead >= 0){ //если считали ovlp.hEvent = NULL; ovlp.OffsetHigh = NULL; ovlp.Offset = GetFileSize(hFile, NULL); WriteFile(hFile, ReadBuf, dwRead, NULL, &ovlp); //пишем в наш файл dwOffset += dwRead; } else{ //не считали, пытаемся повторить скачивание InternetCloseHandle(hInetSession); //закрываем сессию InternetCloseHandle(hInetFile); //закрываем удалённый файл hInetSession = InternetOpen("Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR 1.0.2914)", PRE_CONFIG_INTERNET_ACCESS, NULL, NULL, 0);//пытаемся повторить скачку if(hInetSession == NULL){ CloseHandle(hFile); return -1; } hInetFile = InternetOpenUrl(hInetSession, data.Url, NULL, 0, 0, NULL); if(hInetFile == NULL){ CloseHandle(hFile); InternetCloseHandle(hInetSession); return -1; } InternetSetFilePointer(hInetFile, dwOffset, NULL, FILE_BEGIN, NULL); } } while(dwRead); //закрываем всё лишнее CloseHandle(hFile); InternetCloseHandle(hInetSession); InternetCloseHandle(hInetFile); return 1; } //---------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //------------------------------------------------------------------------- void __fastcall TForm1::UpdateClick(TObject *Sender) { HANDLE hThread; DOWNLOAD_DATA data; strcpy(data.Url, "http://tools.oszone.net/Drongo/QuickKiller_2.20.7z"); data.bFlag = false; hThread = CreateThread(NULL, 0, DownloadThread, &data, 0, NULL); if(hThread == INVALID_HANDLE_VALUE) { ShowMessage("Error. Can't create thread!"); return; } CloseHandle(hThread); } //--------------------------------------------------------------------------- |
|
------- Отправлено: 21:38, 15-04-2010 | #7 |
Старожил Сообщения: 232
|
Профиль | Сайт | Отправить PM | Цитировать Подключите к проекту библиотеку wininet.lib (Project->Add to project->wininet.lib).
|
------- Отправлено: 23:54, 15-04-2010 | #8 |
Будем жить, Маэстро... Сообщения: 6694
|
Профиль | Сайт | Отправить PM | Цитировать ganselo, О, теперь всё скомпилировалось. Но по нажатию на кнопку Обновить, ничего не скачивается.
|
------- Отправлено: 10:40, 16-04-2010 | #9 |
Старожил Сообщения: 232
|
Профиль | Сайт | Отправить PM | Цитировать Думаю проблема в этом:
Первый параметр CreateFile - это название файла (в данном случае, если файл не существует, то CreateFile создаёт его). Попробуйте вместо data.Url написать например "C:\\QuickKiller_2.20.7z". (Название файла лучше парсить из data.Url). |
------- Отправлено: 12:52, 16-04-2010 | #10 |
|
Участник сейчас на форуме | Участник вне форума | Автор темы | Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
Реализация конвейера на Си! NEED HELP! | st031 | Программирование в *nix | 2 | 24-01-2009 10:57 | |
C/C++ - Реализация формулы... | ganselo | Программирование и базы данных | 1 | 20-01-2009 19:38 | |
Разное - Ситема терминалов (реализация) | piling | Microsoft Windows 2000/XP | 2 | 13-02-2008 22:52 | |
Использование ClientSocket и Server | fossil | Программирование и базы данных | 2 | 13-11-2004 17:23 |
|