|
Вопрос # 2 881/ вопрос открыт / |
|
Приветствую, уважаемые эксперты!
Не удивляйтесь "чайниковому" вопросу.
Суть проблемы: приложение, с использованием DataSnap, нормально работает на локальном компе. При переносе клиента на другой комп в той же сети, клиент перестает видеть AppServer! Ошибка "EBrokerError", "No Server Avaliable".
На обоих компах Windows XP SP3. Использую D7.
При разработке руководствовался Марко Кэнту, "Delphi 7 для профессионалов".
Просмотрел в обоих случаях состояние среды при помощи Process Explorer - все одинаково!
Вопрос: В чем проблема, что я не так сделал? Или дайте ссылку, где написано, как надо сделать...
Спасибо!
 |
Вопрос задал: Loki (статус: Посетитель)
Вопрос отправлен: 3 июня 2009, 09:27
Состояние вопроса: открыт, ответов: 0.
|
Мини-форум вопроса
Всего сообщений: 21; последнее сообщение — 6 июня 2009, 23:35; участников в обсуждении: 2.
Страницы: [1] [2] [Следующая »]
|
Вадим К (статус: Академик), 3 июня 2009, 11:08 [#1]:
Книги под рукой нет - по этому сложно судить, что там за код (а код следовало бы привести).
варианты
- обращение к AppServer'у по ip, имени? может его на заданной машине надо запустить.
- Midas?
- используется BDE???
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Loki (статус: Посетитель), 3 июня 2009, 11:40 [#2]:
Благодарю за проявленный интерес!
Обращение к AppServer'у - и по IP пробовал, и по имени, результат один.
Библиотека MIDAS, присутствует в должном месте и на сервере, и на клиенте.
BDE не используется, сервер общается с базой через IBDAC.
Кода, как такового, нет... Remote Data Module содержится в AppServer'е, был запущен и зарегистрирован. В клиенте модуль данных подключается DCOMConnection, все свойства установлены, все работает при расположении клиента и сервера на одном компе...
В чем не могу разобраться - в файле .tlb. Ничего там такого нет...
Вот он:
unit SDIAPP_TLB;
// ************************************************************************ //
// WARNING
// -------
// The types declared in this file were generated from data read from a
// Type Library. If this type library is explicitly or indirectly (via
// another type library referring to this type library) re-imported, or the
// 'Refresh' command of the Type Library Editor activated while editing the
// Type Library, the contents of this file will be regenerated and all
// manual modifications will be lost.
// ************************************************************************ //
// PASTLWTR : 1.2
// File generated on 27.05.2009 18:40:13 from Type Library described below.
// ************************************************************************ //
// Type Lib: C:\Мои программы\QC-NET\QC-Server\QCSrv.tlb (1)
// LIBID: {8D9BF485-F420-4802-97DD-FC76EC3422DF}
// LCID: 0
// Helpfile:
// HelpString: SDIAPP Library
// DepndLst:
// (1) v1.0 Midas, (C:\WINDOWS\system32\midas.dll)
// (2) v2.0 stdole, (C:\WINDOWS\system32\stdole2.tlb)
// ************************************************************************ //
{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers.
{$WARN SYMBOL_PLATFORM OFF}
{$WRITEABLECONST ON}
{$VARPROPSETTER ON}
interface
uses Windows, ActiveX, Classes, Graphics, Midas, StdVCL, Variants;
// *********************************************************************//
// GUIDS declared in the TypeLibrary. Following prefixes are used:
// Type Libraries : LIBID_xxxx
// CoClasses : CLASS_xxxx
// DISPInterfaces : DIID_xxxx
// Non-DISP interfaces: IID_xxxx
// *********************************************************************//
const
// TypeLibrary Major and minor versions
SDIAPPMajorVersion = 1;
SDIAPPMinorVersion = 0;
LIBID_SDIAPP: TGUID = '{8D9BF485-F420-4802-97DD-FC76EC3422DF}';
IID_IQC_Server: TGUID = '{307F1DEC-FCEC-4216-AFD6-FB839C18350B}';
CLASS_QC_Server: TGUID = '{79650AC0-E35C-46A1-B50C-9B81FBCC2B40}';
IID_IQCServer: TGUID = '{2C4A2A74-489D-4266-B90D-9A6BC17AF484}';
CLASS_QCServer: TGUID = '{6CB0BFBD-5481-4D1A-9ABF-F70FBDDED24E}';
type
// *********************************************************************//
// Forward declaration of types defined in TypeLibrary
// *********************************************************************//
IQC_Server = interface;
IQC_ServerDisp = dispinterface;
IQCServer = interface;
IQCServerDisp = dispinterface;
// *********************************************************************//
// Declaration of CoClasses defined in Type Library
// (NOTE: Here we map each CoClass to its Default Interface)
// *********************************************************************//
QC_Server = IQC_Server;
QCServer = IQCServer;
// *********************************************************************//
// Interface: IQC_Server
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {307F1DEC-FCEC-4216-AFD6-FB839C18350B}
// *********************************************************************//
IQC_Server = interface(IAppServer)
['{307F1DEC-FCEC-4216-AFD6-FB839C18350B}']
end;
// *********************************************************************//
// DispIntf: IQC_ServerDisp
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {307F1DEC-FCEC-4216-AFD6-FB839C18350B}
// *********************************************************************//
IQC_ServerDisp = dispinterface
['{307F1DEC-FCEC-4216-AFD6-FB839C18350B}']
function AS_ApplyUpdates(const ProviderName: WideString; Delta: OleVariant; MaxErrors: Integer;
out ErrorCount: Integer; var OwnerData: OleVariant): OleVariant; dispid 20000000;
function AS_GetRecords(const ProviderName: WideString; Count: Integer; out RecsOut: Integer;
Options: Integer; const CommandText: WideString; var Params: OleVariant;
var OwnerData: OleVariant): OleVariant; dispid 20000001;
function AS_DataRequest(const ProviderName: WideString; Data: OleVariant): OleVariant; dispid 20000002;
function AS_GetProviderNames: OleVariant; dispid 20000003;
function AS_GetParams(const ProviderName: WideString; var OwnerData: OleVariant): OleVariant; dispid 20000004;
function AS_RowRequest(const ProviderName: WideString; Row: OleVariant; RequestType: Integer;
var OwnerData: OleVariant): OleVariant; dispid 20000005;
procedure AS_Execute(const ProviderName: WideString; const CommandText: WideString;
var Params: OleVariant; var OwnerData: OleVariant); dispid 20000006;
end;
// *********************************************************************//
// Interface: IQCServer
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {2C4A2A74-489D-4266-B90D-9A6BC17AF484}
// *********************************************************************//
IQCServer = interface(IAppServer)
['{2C4A2A74-489D-4266-B90D-9A6BC17AF484}']
end;
// *********************************************************************//
// DispIntf: IQCServerDisp
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {2C4A2A74-489D-4266-B90D-9A6BC17AF484}
// *********************************************************************//
IQCServerDisp = dispinterface
['{2C4A2A74-489D-4266-B90D-9A6BC17AF484}']
function AS_ApplyUpdates(const ProviderName: WideString; Delta: OleVariant; MaxErrors: Integer;
out ErrorCount: Integer; var OwnerData: OleVariant): OleVariant; dispid 20000000;
function AS_GetRecords(const ProviderName: WideString; Count: Integer; out RecsOut: Integer;
Options: Integer; const CommandText: WideString; var Params: OleVariant;
var OwnerData: OleVariant): OleVariant; dispid 20000001;
function AS_DataRequest(const ProviderName: WideString; Data: OleVariant): OleVariant; dispid 20000002;
function AS_GetProviderNames: OleVariant; dispid 20000003;
function AS_GetParams(const ProviderName: WideString; var OwnerData: OleVariant): OleVariant; dispid 20000004;
function AS_RowRequest(const ProviderName: WideString; Row: OleVariant; RequestType: Integer;
var OwnerData: OleVariant): OleVariant; dispid 20000005;
procedure AS_Execute(const ProviderName: WideString; const CommandText: WideString;
var Params: OleVariant; var OwnerData: OleVariant); dispid 20000006;
end;
// *********************************************************************//
// The Class CoQC_Server provides a Create and CreateRemote method to
// create instances of the default interface IQC_Server exposed by
// the CoClass QC_Server. The functions are intended to be used by
// clients wishing to automate the CoClass objects exposed by the
// server of this typelibrary.
// *********************************************************************//
CoQC_Server = class
class function Create: IQC_Server;
class function CreateRemote(const MachineName: string): IQC_Server;
end;
// *********************************************************************//
// The Class CoQCServer provides a Create and CreateRemote method to
// create instances of the default interface IQCServer exposed by
// the CoClass QCServer. The functions are intended to be used by
// clients wishing to automate the CoClass objects exposed by the
// server of this typelibrary.
// *********************************************************************//
CoQCServer = class
class function Create: IQCServer;
class function CreateRemote(const MachineName: string): IQCServer;
end;
implementation
uses ComObj;
class function CoQC_Server.Create: IQC_Server;
begin
Result := CreateComObject(CLASS_QC_Server) as IQC_Server;
end;
class function CoQC_Server.CreateRemote(const MachineName: string): IQC_Server;
begin
Result := CreateRemoteComObject(MachineName, CLASS_QC_Server) as IQC_Server;
end;
class function CoQCServer.Create: IQCServer;
begin
Result := CreateComObject(CLASS_QCServer) as IQCServer;
end;
class function CoQCServer.CreateRemote(const MachineName: string): IQCServer;
begin
Result := CreateRemoteComObject(MachineName, CLASS_QCServer) as IQCServer;
end;
end.
Что бы это могло быть?
Спасибо!
|
|
Вадим К (статус: Академик), 3 июня 2009, 12:58 [#3]:
Подозреваю, что клиент ищет сервер на локальном компьютере
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Loki (статус: Посетитель), 3 июня 2009, 13:34 [#4]:
Спасибо, Вадим К, логичное предположение. А как же направить его усилия в сеть? У Кэнту на этот счет ничего не сказано. Подразумевается, что, не найдя сервер на локальном, он станет опрашивать другие компы в сети? Но ему же в явном виде указывается адрес компа с сервером (в свойстве "Computer Name" DCOMConnection)!
|
|
Вадим К (статус: Академик), 3 июня 2009, 13:56 [#5]:
Если Кэнту умалчивает, значит либо не знает, либо плохо ориентируется. У него такое есть. Просто не хочет путать читателя.
Подозреваю, что на локальной машине надо зарегистрировать интерфейсы. И не просто зарегистрировать, а ещё и правильно.
Вся технология DCOM ведь хитро построена. На каждом клиенте есть сервер-заглушка. При обращении к нему происходит "заворачивание в пакеты" и отправка по сети. А там такая же заглушка разворачивает и отдает локальному серверу. Это конечно утрировано, но прояснит некоторые детали.
Так вот, я думаю, что нет этой заглушки на клиенте или она "не туда смотрит".
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Вадим К (статус: Академик), 3 июня 2009, 14:48 [#7]:
Зайти в "панель управления"- Адиминистрирование - Component Services
либо запустить C:\WINDOWS\system32\Com\comexp.msc (путь по необходимости корректируется)
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Loki (статус: Посетитель), 3 июня 2009, 16:36 [#8]:
Спасибо, Вадим К! Поиграю на этом поле, посмотрю, что из этого выйдет... Завтра расскажу, что получилось. Спасибо!
|
|
Loki (статус: Посетитель), 4 июня 2009, 15:31 [#9]:
Доброго времени суток!
Покопался в "Службе компонентов" на "серверном" компе, нашел записи, соответствующие моему серверу. Задал в свойствах протоколы, но спрашивают еще и "конечные точки" - не знаю, что это, поэтому оставил "по умолчанию". Толку от этих потуг не было... Еще обратил внимание - тип сервера "локальный".
Наверное, что-то не так я сделал. Где бы почитать об этом, кроме Кэнту? Нет ли полезных ссылок?
Спасибо!
|
|
Вадим К (статус: Академик), 4 июня 2009, 16:45 [#10]:
Может просто сервер был установлен как локальный и он не не слушает внешние подключиения и всего то?
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Loki (статус: Посетитель), 4 июня 2009, 16:49 [#11]:
Сервер создавался на этом компе... Но на другом компе он тоже так же себя ведет. Но где же у него задается это свойство?
|
|
Loki (статус: Посетитель), 5 июня 2009, 16:12 [#12]:
День добрый, Вадим К! Вчера попробовал вместо DCOMConnection поставил SocetConnection. О, чудо! Есть коннект, и клиент добросовестно получает получает данные от сервера . Но при попытке записать данные в базу, серверный комп жестко виснет. Перегрузить его удается только кнопкой... В чем может быть засада?
Спасибо!
|
|
Вадим К (статус: Академик), 5 июня 2009, 16:18 [#13]:
а если данные в базу не писать, то всё работает хорошо?
код записи в базу тоже хорошо бы увидеть.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Loki (статус: Посетитель), 5 июня 2009, 16:52 [#14]:
Если не писать - то все хорошо, Query проходят прекрасно, без всяких фокусов. Запись в базу - через компоненты StoredProc сервера, активируются на стороне клиента ClientDataSet.Execute после передачи параметров. Локально эта схема работает без фокусов.
Или это фокусы scktsrvr...
|
|
Loki (статус: Посетитель), 5 июня 2009, 16:57 [#15]:
Код записи:
ClientDataSet.FetchParams;
ClientDataSet.Params.ParamValues['..']:=...;
.
.
Try
ClientDataSet.Execute;
Except
MessageDlg('Не удалось...',...);
Abort;
end;
|
|
Вадим К (статус: Академик), 5 июня 2009, 17:40 [#16]:
толку с этого кода конечно мало. для начала хорошо бы выяснить, в какой именно строке подвисает. Для этого оптимальней всего пользоваться логированием. почитайте здесь https://www.delphi-int.ru/articles/40/
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Loki (статус: Посетитель), 5 июня 2009, 22:30 [#17]:
Спасибо, Вадим К!
У меня сложилось впечатление, что виснет не сам клиент, а именно система, после того, как клиент что-то делает с сокетом. Или сервер завешивает систему... А в сервере и кода-то практически нет!
Компонент SocetConnection предложил по умолчанию порт 211, я не стал менять это значение. Не может быть в этом ошибки?
Спасибо!
|
|
Вадим К (статус: Академик), 5 июня 2009, 23:25 [#18]:
Вряд ли причина в сокете - Вы же сами писали, что если в базу не писать, то всё работает. Попробуйте заменить запись в базу на фиктивную (на пустышку-заглушку). Или например запросы писать в файл. просто сохранять. Если это заработает - тогда причина в движке базы (а я подозреваю, что она там).
В таких сложных случаях я всегда применяю метод "делить пополам" - то есть, часть кода заменяем пустышкой, которая симулирует работу части кода.
Как только находиться костяк кода, который работает - начинается обратный процесс - раскомментирование кода.
Но бывает жестокий случай - когда два куска кода блокируют друг дружку. Надо помнить об этом.
И самое важное - логи, логи, логи... Иногда они так спасают...
Кстати, Вы так и не показали ту строку, с которой всё зависает. Или это после выполнения кода.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Loki (статус: Посетитель), 6 июня 2009, 11:05 [#19]:
Доброе утро, уважаемый Вадим К!
Ситуация прояснилась. Проблема - со сторонними компонентами. Вешает систему попытка вставить запись в базу напрямую из грида - единственное место в клиенте, где это возможно. Если писать стандартным способом, через StoredProc, то никаких неприятных последствий не наступает!
Единственная неприятность - в начале сеанса на всех компах приходится вручную запускать scktsrvr. Можно конечно добавить его в AutoExec или запускать клиента .bat-ом. Но это уже мелочи, по сравнению с тем, с чего началось...
Спасибо Вам огромное, Вадим К!
|
|
Вадим К (статус: Академик), 6 июня 2009, 11:38 [#20]:
То есть данные брались с DbGrid'a??? напрямую? Это может объяснить часть глюков.
По поводу запуска клиента - кто мешает в программе (в клиенте) проверять, запушен ли scktsrvr и запускать его. И лишь потом делать попытку коннекта. Кстати, можно просто сразу пытаться подключиться, и если не получается - запускать scktsrvr и ещё раз.
Галочка "подтверждения прочтения" - вселенское зло.
|
Страницы: [1] [2] [Следующая »]
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|