Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - [решено] Реализация обновления программы - ClientSocket и ClientServer

Ответить
Настройки темы
C/C++ - [решено] Реализация обновления программы - ClientSocket и ClientServer

Аватара для Drongo

Будем жить, Маэстро...


Сообщения: 6694
Благодарности: 1393


Конфигурация

Профиль | Сайт | Отправить PM | Цитировать


Вложения
Тип файла: rar ClientSocket.rar
(14.9 Kb, 42 просмотров)
Привет. Заранее приношу извинение если буду использовать неверную терминологию, но до недавнего времени у меня небыло необходимости в использовании этих компонентов и самой технологии. Задача в общем-то такова, есть клиет-программа, на сервере есть обновления к этой программе, нужно по нажатию на кнопку\пункт меню "Обновить", чтобы программа скачала только те модули, которые новее тех, которые присутствуют рядом с программой. Аналог такого обновления, любой антивирус или AVZ. Поискал в сети, нашёл статью - Передача файлов в C++Builder через TClientSocket и TServerSocket. По примеру сделал тестовую программу, в рамках одного компьютера она работает, но там, в примере, есть клиентская часть и серверная.

Вот представьте, что наше обновление - этот файл - QuickKiller_2.20.7z нужно скачать и находится он здесь - http://tools.oszone.net/Drongo/QuickKiller_2.20.7z. Но скачивать нужно как обновление (как менеджер закачек), а не через диалоговое окно "Сохранить файл".

Архив простенького проекта прикрепил, собирал по примеру выше, при нажатии на кнопку "Скачать" устанавливает соединение и на этом всё. Собственно, я не знаю в какую сторону смотреть и те ли компоненты, которые я выбрал, нужны для этих целей? Среда разработки
Цитата:
Borland C++ Builder 6.0 Enterprise Suite
Спасибо.

-------
Правильная постановка вопроса свидетельствует о некотором знакомстве с делом.
3нание бывает двух видов. Мы сами знаем предмет — или же знаем, где найти о нём сведения.
[Quick Killer 3.0 Final [OSZone.net]] | [Quick Killer 3.0 Final [SafeZone.cc]] | [Парсер логов Gmer] | [Парсер логов AVZ]

http://tools.oszone.net/Drongo/Userbar/SafeZone_cc.gif


Отправлено: 20:43, 14-04-2010

 

Аватара для ganselo

Старожил


Сообщения: 232
Благодарности: 90

Профиль | Сайт | Отправить 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



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для Drongo

Будем жить, Маэстро...


Сообщения: 6694
Благодарности: 1393

Профиль | Сайт | Отправить PM | Цитировать


ganselo, спасибо, но если можно подробнее, куда и как этот код нужно подставить? Я не понимаю.

-------
Правильная постановка вопроса свидетельствует о некотором знакомстве с делом.
3нание бывает двух видов. Мы сами знаем предмет — или же знаем, где найти о нём сведения.
[Quick Killer 3.0 Final [OSZone.net]] | [Quick Killer 3.0 Final [SafeZone.cc]] | [Парсер логов Gmer] | [Парсер логов AVZ]

http://tools.oszone.net/Drongo/Userbar/SafeZone_cc.gif


Отправлено: 12:32, 15-04-2010 | #3


Аватара для ganselo

Старожил


Сообщения: 232
Благодарности: 90

Профиль | Сайт | Отправить 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


Аватара для Drongo

Будем жить, Маэстро...


Сообщения: 6694
Благодарности: 1393

Профиль | Сайт | Отправить PM | Цитировать


ganselo, То что есть комментарии это хорошо, но как правильно эту функцию объявить? Как функцию вызвать? Откуда?
Цитата Drongo:
куда и как этот код нужно подставить? »
Вот обработчик кнопки Обновить, как мне отсюда правильно вызывать функцю DownloadThread(LPVOID lpParam);
Код: Выделить весь код
...
// Обновление----------------------------------------------------------
void __fastcall TForm1::UpdateClick(TObject *Sender)
{
   // Как вызвать эту функцию - DownloadThread?
}
//---------------------------------------------------------------------------
...

-------
Правильная постановка вопроса свидетельствует о некотором знакомстве с делом.
3нание бывает двух видов. Мы сами знаем предмет — или же знаем, где найти о нём сведения.
[Quick Killer 3.0 Final [OSZone.net]] | [Quick Killer 3.0 Final [SafeZone.cc]] | [Парсер логов Gmer] | [Парсер логов AVZ]

http://tools.oszone.net/Drongo/Userbar/SafeZone_cc.gif


Отправлено: 16:15, 15-04-2010 | #5


Аватара для ganselo

Старожил


Сообщения: 232
Благодарности: 90

Профиль | Сайт | Отправить 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


Аватара для Drongo

Будем жить, Маэстро...


Сообщения: 6694
Благодарности: 1393

Профиль | Сайт | Отправить PM | Цитировать


ganselo, Вот такая ошибка компоновщика получается.

Цитата:
[Компоновщик Ошибка] Unresolved external 'InternetReadFile' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER6\PROJECTS\CLIENTSOCKET\CLIENTSOCKET1.OBJ
[Компоновщик Ошибка] Unresolved external 'InternetOpenA' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER6\PROJECTS\CLIENTSOCKET\CLIENTSOCKET1.OBJ
[Компоновщик Ошибка] Unresolved external 'InternetOpenUrlA' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER6\PROJECTS\CLIENTSOCKET\CLIENTSOCKET1.OBJ
[Компоновщик Ошибка] Unresolved external 'InternetSetFilePointer' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER6\PROJECTS\CLIENTSOCKET\CLIENTSOCKET1.OBJ
[Компоновщик Ошибка] Unresolved external 'InternetCloseHandle' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER6\PROJECTS\CLIENTSOCKET\CLIENTSOCKET1.OBJ
Вот такой код использую. Заголовочный файл WinInet.h включён. Что я делаю не так?
Код: Выделить весь код
//---------------------------------------------------------------------------
#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);
}
//---------------------------------------------------------------------------

-------
Правильная постановка вопроса свидетельствует о некотором знакомстве с делом.
3нание бывает двух видов. Мы сами знаем предмет — или же знаем, где найти о нём сведения.
[Quick Killer 3.0 Final [OSZone.net]] | [Quick Killer 3.0 Final [SafeZone.cc]] | [Парсер логов Gmer] | [Парсер логов AVZ]

http://tools.oszone.net/Drongo/Userbar/SafeZone_cc.gif


Отправлено: 21:38, 15-04-2010 | #7


Аватара для ganselo

Старожил


Сообщения: 232
Благодарности: 90

Профиль | Сайт | Отправить PM | Цитировать


Подключите к проекту библиотеку wininet.lib (Project->Add to project->wininet.lib).

-------
К величайшему сожалению "история учит нас тому, что она ничему не учит".

Это сообщение посчитали полезным следующие участники:

Отправлено: 23:54, 15-04-2010 | #8


Аватара для Drongo

Будем жить, Маэстро...


Сообщения: 6694
Благодарности: 1393

Профиль | Сайт | Отправить PM | Цитировать


ganselo, О, теперь всё скомпилировалось. Но по нажатию на кнопку Обновить, ничего не скачивается.

-------
Правильная постановка вопроса свидетельствует о некотором знакомстве с делом.
3нание бывает двух видов. Мы сами знаем предмет — или же знаем, где найти о нём сведения.
[Quick Killer 3.0 Final [OSZone.net]] | [Quick Killer 3.0 Final [SafeZone.cc]] | [Парсер логов Gmer] | [Парсер логов AVZ]

http://tools.oszone.net/Drongo/Userbar/SafeZone_cc.gif


Отправлено: 10:40, 16-04-2010 | #9


Аватара для ganselo

Старожил


Сообщения: 232
Благодарности: 90

Профиль | Сайт | Отправить PM | Цитировать


Думаю проблема в этом:
Код: Выделить весь код
hFile = CreateFile(data.Url, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); //открываем файл для сохранения
Первый параметр CreateFile - это название файла (в данном случае, если файл не существует, то CreateFile создаёт его). Попробуйте вместо data.Url написать например "C:\\QuickKiller_2.20.7z". (Название файла лучше парсить из data.Url).

-------
К величайшему сожалению "история учит нас тому, что она ничему не учит".

Это сообщение посчитали полезным следующие участники:

Отправлено: 12:52, 16-04-2010 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - [решено] Реализация обновления программы - ClientSocket и ClientServer

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Реализация конвейера на Си! 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




 
Переход