Конференция "Corba" » Реализация собственного транспорта для DCOM [Delphi]
 
  • 5ye (15.07.10 11:00) [0]
    Задача: реализовать взаимодействие с собственным сервером автоматизации (созданным в EXE-файле) в локальной сети без применения DCOM ввиду известных проблем (закрытый администраторами порт 135, сложности с настройками безопасности и проч.).

    Много ссылок перекопал (в том числе и схожую ветку http://pda.delphimaster.net/?id=1241400963&n=8). Написал тестовую программу, работающую опционально в режиме сервера или клиента.

    В первом случае программа открывает серверный сокет, локально создает мой тестовый объект автоматизации, к которому подключает создаваемый IRpcStubBuffer.

    Во втором -  клиентское активное TCP-подключение и IRpcProxyBuffer, подключенный к собственной реализации IRpcChannelBuffer.

    Код IRpcChannelBuffer.SendReceive


    function TRpcChannel.SendReceive(var message: TRpcOleMessage;
     var status: Longint): HResult; stdcall;
    var
     TmpBuf: TDinamicByteArray;
    begin
     case fDCOMProxy.FType of
       ctClient:
       begin
         fDCOMProxy.FCurConnector := FOwner;
         TmpBuf := nil;
         // формирование пакета для пересылки по TCP/IP
         AddIntegerToDArray(0, TmpBuf);
         MakeBuffer(message, FOwner.FIID, TmpBuf);
         PInteger(@TmpBuf[0])^ := Length(TmpBuf) - sizeof(integer);
         ResetEvent(fDCOMProxy.WaitRxBufEvent);
         fDCOMProxy.cs1.Socket.SendBuf(TmpBuf[0], Length(TmpBuf));
         repeat
           case MsgWaitForMultipleObjects(1, fDCOMProxy.WaitRxBufEvent, false,
             INFINITE, QS_ALLINPUT) of
             WAIT_OBJECT_0: break;
           else
             Application.ProcessMessages;
           end;
         until false;
         TmpBuf := fDCOMProxy.ProxyRxBuf;
         MakeMessage(TmpBuf, FOwner.FIID, message);      
       end;
       ctServer:;
       ctLocal:
       begin
         fDCOMProxy.FCurConnector := FOwner;
         fDCOMProxy.FCurConnector.IStub.Invoke(message, Self);
       end;
     end;
     Result := S_OK;  
    end;




    где



    type
     TDinamicByteArray = array of byte;

    procedure MakeMessage(Buf: TDinamicByteArray; out IID: TIID;
     out OleMessage: TRpcOleMessage);
    var
     Index: integer;
    begin
     ZeroMemory(@OleMessage, Sizeof(OleMessage));
     CopyMemory(@IID, @Buf[0], sizeof(IID));
     Index := sizeof(IID);
     OleMessage.dataRepresentation := GetIntegerFromDArray(Index, Buf);
     OleMessage.iMethod := GetIntegerFromDArray(Index, Buf);
     OleMessage.rpcFlags := GetIntegerFromDArray(Index, Buf);
     OleMessage.cbBuffer := GetIntegerFromDArray(Index, Buf);
     OleMessage.Buffer := GlobalAllocPtr(GPTR, OleMessage.cbBuffer);
     CopyMemory(OleMessage.Buffer, @Buf[Index], OleMessage.cbBuffer);
    end;

    procedure MakeBuffer(OleMessage: TRpcOleMessage; IID: TIID;
     var Buf: TDinamicByteArray);
    begin
     AddDataToDarray(IID, sizeof(IID), Buf);
     AddIntegerToDArray(OleMessage.dataRepresentation, Buf);
     AddIntegerToDArray(OleMessage.iMethod, Buf);
     AddIntegerToDArray(OleMessage.rpcFlags, Buf);
     AddIntegerToDArray(OleMessage.cbBuffer, Buf);
     AddDataToDarray(OleMessage.Buffer^, OleMessage.cbBuffer, Buf);
    end;




    В общем все сводится к пересылке в неизменном виде содержимого TRpcOleMessage по TCP/IP, вызов на строне сервера IStub.Invoke() и обратная пересылка ответа.

    Решение работает на локальной машине при указании контекста   dwDestContext := CLSCTX_LOCAL_SERVER в методе IRpcChannelBuffer.GetDestCtx().

    Проблемы начинаются с удаленной пересылкой интерфейсов. Используемые интерфейсы сервера автоматизации наследуются от IDispatch и поддаются автоматическому маршалингу (по крайней мере при работе в контексте CLSCTX_LOCAL_SERVER). Однако при работе в сети выскакивает ошибка: "не найден указанный источник экспорта объекта". Замена контекста на CLSCTX_REMOTE_SERVER приводит к неработоспособности даже в локальном взаимодейтвии Proxy/stub в контексте одного процесса, выдавая при попытке пересылки интерфейса ошибку "заглушке переданы неправильные данные".

    Собственно, вопрос: можно ли заставить работать такой механизм (только без применения ручного маршалинга реализацией IMarshal, ведь DCOM как-то умеет пересылать интерфейсы по сети)?
  • Slym (15.07.10 14:17) [1]
    C:\Program Files\Borland\Delphi7\Source\Vcl\ScktSrvr.dpr
    как-то по сети работает
  • 5ye (15.07.10 14:48) [2]
    Там требуется реализация IDataIntercept для пересылаемых интрефейсов (опять же ручной маршалинг).
    Решение есть 100%. Проверял свой сервер автоматизации на демке платной утилиты с http://www.dcomlab.ru/. Но КАК они это сделали? Для меня принципиально получить именно возможность реализации своего транспорта на случай дальнейшей необходимости отойти от TCP/IP.
 
Конференция "Corba" » Реализация собственного транспорта для DCOM [Delphi]
Есть новые Нет новых   [134427   +34][b:0][p:0.003]