【專案背景】:要開發一套客戶本地WebService+云端WebService的系統。客戶本地的WebService用來封裝云端服務,加密解密業務引數,傳遞至云端處理,并異步通知客戶自有系統。
【技術選型】:本地WebService開發:Delphi 10 Seattle+IIS部署;云端:java+Apache部署。測驗客戶端:Delphi 10 Seattle。
【開發除錯環境】:本地:win10+IIS10;云端:win7+java+Tomcat。本地和云端都在同一內網環境。
【問題概述】:部署在IIS中的服務提供兩類介面:不依賴于云端的介面(本地介面)和依賴于云端的介面(云端介面)。
現象1:測驗客戶端訪問IIS服務,本地介面正常,訪問云端介面失敗。提示Access violation at address XXX in module 'w3wp.exe'. Execution of address XXX。
【前期排查】:
1:測驗客戶端直接引入云端WebService的wsdl,直接訪問云端服務的介面,運行正常。
2:使用Delphi創建一個Stand-alone程式,引入部署在IIS中的功能單元,編譯出一個除錯用的WebService程式運行,測驗客戶端訪問除錯用的WebService程式,訪問云端介面正常。
3.修改本地WebService代碼,逐步細化。
3.1 使用引入的WSDL單元提供的GetXXX方法,獲得一個服務物件ObjService(成功)。
3.2 判斷ObjService是否為nil。不為nil。
3.3 使用ObjService呼叫云端方法,出現例外。例外訊息為Access violation at address XXX in module 'w3wp.exe'. Execution of address XXX
【云端WebService引入WSDL后的代碼段】
type
ServiceTest = interface(IInvokable)
['{EF9003DD-7741-A0E6-26EE-80D1A9E47D69}']
function getValue(const arg0: string): string; stdcall;
end;
function GetServiceTest(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): ServiceTest;
implementation
uses System.SysUtils;
function GetServiceTest(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): ServiceTest;
const
defWSDL = 'http://10.19.128.136:8080/ServiceTest?wsdl';
defURL = 'http://10.19.128.136:8080/ServiceTest';
defSvc = 'ServiceTestService';
defPrt = 'ServiceTestPort';
var
RIO: THTTPRIO;
begin
Result := nil;
if (Addr = '') then
begin
if UseWSDL then
Addr := defWSDL
else
Addr := defURL;
end;
if HTTPRIO = nil then
RIO := THTTPRIO.Create(nil)
else
RIO := HTTPRIO;
try
Result := (RIO as ServiceTest);
if UseWSDL then
begin
RIO.WSDLLocation := Addr;
RIO.Service := defSvc;
RIO.Port := defPrt;
end else
RIO.URL := Addr;
finally
if (Result = nil) and (HTTPRIO = nil) then
RIO.Free;
end;
end;
initialization
{ ServiceTest }
InvRegistry.RegisterInterface(TypeInfo(ServiceTest), 'http://test.servyou.com/', 'UTF-8');
InvRegistry.RegisterDefaultSOAPAction(TypeInfo(ServiceTest), '');
InvRegistry.RegisterInvokeOptions(TypeInfo(ServiceTest), ioDocument);
{ ServiceTest.getValue }
InvRegistry.RegisterMethodInfo(TypeInfo(ServiceTest), 'getValue', '',
'[ReturnName="return"]', IS_OPTN or IS_UNQL);
InvRegistry.RegisterParamInfo(TypeInfo(ServiceTest), 'getValue', 'arg0', '',
'', IS_UNQL);
InvRegistry.RegisterParamInfo(TypeInfo(ServiceTest), 'getValue', 'return', '',
'', IS_UNQL);
【本地WebService呼叫云端WebService的代碼段】
function TDataPreVerify.CloudTest(const arg0: string): string;
var
vRet: ServiceTest;
begin
try
vRet := GetServiceTest;
except
on e : Exception do
begin
Result := e.Message;
Exit;
end;
end;
if vRet = nil then
Result := '遠程服務為nil'
else
begin
try
Result := vRet.getValue(arg0);
except
on e : Exception do
begin
Result := '遠程服務正常,介面訪問例外:'+e.Message;
Exit;
end;
end;
Result := '測驗看看'+ Result;//GetServiceTest.getValue(arg0);
end;
end;
以上代碼,測驗客戶端呼叫部署在IIS的服務之后,會回傳“遠程服務正常,介面訪問例外:Access violation at address 000001FC00495C30 in module 'w3wp.exe'. Execution of address 000001FC00495C30”,證明物件是能創建出來,并且不為空的,但是呼叫方法出了問題。
目前懷疑是IIS的配置上可能存在一些問題(某些配置沒有做或者權限沒有開);或者說win10不是服務器系統,會不會IIS存在功能不全的情況;或者是IIS本來就不支持訪問其他WebService的能力?因為用的Delphi創建的Stand-alone的服務運行的時候,就可以正常訪問云端介面,和上面走的是同樣的代碼實作,所以從代碼上來說應該是沒有問題的。
下面是IIS配置之后,web.config檔案的內容:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<directoryBrowse enabled="true" />
</system.webServer>
</configuration>
由于IIS不太熟悉,所以在IIS中配置WebService只做了簡單的幾步操作,建應用程式池->建一個網站->建一個應用程式->設定目錄可瀏覽->設定程式處理映射,ISAPI-dll指向提供WebService的dll。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/56597.html
標籤:網絡通信/分布式開發
