由於服務器端的IP地址是變化的所以客戶端在登錄前需要修改連接地址
思路一修改客戶端配置文件nfig的<client>節點上<endpoint>的address
處理方法如下但是這個方法有個缺點就是即便修改配置文件中的地址後即便是新創建的客戶端代理對象其address依然是修改前的地址除非重新啟動客戶端
方法如下
private void UpdateConfig(string serverIPAddress string serverPort)
{
//Configuration config = ConfigurationManagerOpenExeConfiguration(AssemblyGetEntryAssembly()Location);
Configuration config = ConfigurationManagerOpenExeConfiguration(ConfigurationUserLevelNone);
ConfigurationSectionGroup sct = configSectionGroups[systemserviceModel];
ServiceModelSectionGroup serviceModelSectionGroup = sct as ServiceModelSectionGroup;
ClientSection clientSection = serviceModelSectionGroupClient;
foreach (ChannelEndpointElement item in clientSectionEndpoints)
{
string pattern = ://*/;
string address = itemAddressToString();
string replacement = stringFormat(://{}:{}/ serverIPAddress serverPort);
address = RegexReplace(address pattern replacement);
itemAddress = new Uri(address);
}
configSave(ConfigurationSaveModeModified);
ConfigurationManagerRefreshSection(systemserviceModel);
}
至於是否有辦法可以刷新這個地址答案是否定的原因是Net framework 在客戶端啟動時就將nfig 讀入了而且後面即便修改了nfig文件也不會刷新nfig的內容
至於為什麼不重新加載文章【】說在通常使用時不可能的如果要刷新nfig的內容需要知道nfig的內容何時改變了這可以通過注冊文件改變通知事件來實現然而一旦檢測到nfig的內容改變需要通知所有使用了nfig的組件
那麼問題就來了 Net framework 如何來知道哪些組件使用了nfig由於注冊機制的缺陷是不可能做到進一步說實現了所有需要讀取nfig的組件在Net framework中注冊這個機制當Net framework檢測到nfig的改變它將通知每個注冊組件nfig已改變那麼組件該現在該如何做呢?
為了讓nfig新的改變生效組件不得不重新啟動它自己這意味著組件需要能夠刷新舊的配置以及那些基於舊的配置的數據和行為然後讀取新的配置並從新的配置開始刷新
這是不可能的舉個綁定策略的例子如果舊的綁定策略認為它需要從裝配件(assembly)A中獲得版本而新的策略認為它需要從從裝配件(assembly)A中獲得版本在裝配件(assembly)A的版本已經加載的情況下 Net framework 無法為新的綁定策略從裝配件(assembly)A中獲得版本
僅僅只有一小部分的配置數據可以刷新這些包括無狀態影響或是影響很容易被消除的配置數據緩存大小就是一個好的例子在緩存大小改變上你能重新設置緩存大小數據仍然保存著或者簡單移除舊的緩存並開啟一個新的緩存塊
通常來說當nfig發生改變時確保所有組件一致性的方法是重啟應用程序這個方法Net framework所采用的
ASPNet有內置的關於nfig發生改變的檢測機制它在監控nfig上發生的改變一旦它檢測到改變它將關閉舊的應用程序重新啟動新的應用程序
因此Net framework將來也不會提供配置數據刷新的特征如果你認為這個對於你很重要你必須自己去實現這個
幸運的是企業庫(Enterprise Library)那幫人理解了這個需求他們在最新的企業庫版本中開發了個應用程序配置塊(Configuration Application Block)
思路二如何在不重新啟動客戶端的情況下改變服務器端的地址總共有兩大類各有兩種情況
第一大類對於使用代理類
兩種情況
()不使用身份驗證
()使用身份驗證
/// <summary>
/// 調用方案一
/// </summary>
/// <param name=serverAddress>服務器地址</param>
private static void CallFirstScheme(string serverAddress)
{
/*
/*方案一對於使用代理類*/
ConsoleWriteLine(方案一);
//測試連接(不使用身份驗證)
ConsoleWriteLine( 創建代理對象 userNamePwdValidator);
EndpointAddress address = new EndpointAddress(nettcp:// + serverAddress + :/UserNamePwdValidator/UserNamePwdValidatorService);
UserNamePwdValidatorClient userNamePwdValidator
= new UserNamePwdValidatorClient(UserNamePwdValidatorService address);
bool result = userNamePwdValidatorValidate(stringEmpty stringEmpty);
ConsoleWriteLine( 測試連接成功);
//驗證用戶名和密碼(與測試連接調用同樣的接口不使用身份驗證)
//bool result = userNamePwdValidatorValidate(admin admin);
//調用服務(使用身份驗證)
ConsoleWriteLine( 創建服務代理對象 user);
UserClient user = new UserClient(UserService);
userEndpointAddress = new EndpointAddress(new Uri(nettcp:// + serverAddress + :/User)
userEndpointAddressIdentity userEndpointAddressHeaders);
userClientCredentialsUserNameUserName = admin;
userClientCredentialsUserNamePassword = admin;
userInsert();
ConsoleWriteLine( 調用服務成功/n);
/*方案一結束*/
}
第二大類對於使用工廠類
兩種情況
()不使用身份驗證
()使用身份驗證
/// <summary>
/// 調用方案二
/// </summary>
/// <param name=serverAddress>服務器地址</param>
private static void CallSecondScheme(string serverAddress)
{
/*方案二對於使用工廠類*/
ConsoleWriteLine(方案二);
//測試連接(不使用身份驗證)
ConsoleWriteLine( 創建接口對象 userNamePwdValidator);
ChannelFactory<WCFContractsIUserNamePwdValidator> channelFactory
= new ChannelFactory<WCFContractsIUserNamePwdValidator>(Another_UserNamePwdValidatorService);
channelFactoryEndpointAddress = new EndpointAddress(nettcp:// + serverAddress + :/UserNamePwdValidator/UserNamePwdValidatorService);
WCFContractsIUserNamePwdValidator otherUserNamePwdValidator = channelFactoryCreateChannel();
bool result = otherUserNamePwdValidatorValidate(stringEmpty stringEmpty);
ConsoleWriteLine( 測試連接成功);
//驗證用戶名和密碼(與測試連接調用同樣的接口不使用身份驗證)
//bool result = userNamePwdValidatorValidate(admin admin);
//調用服務
ConsoleWriteLine( 創建接口對象 user);
ChannelFactory<WCFContractsIUser> otherChannelFactory = new ChannelFactory<WCFContractsIUser>(Another_UserService);
otherChannelFactoryCredentialsUserNameUserName = admin;
otherChannelFactoryCredentialsUserNamePassword = admin;
otherChannelFactoryEndpointAddress = new EndpointAddress(new Uri(nettcp:// + serverAddress + :/User)
otherChannelFactoryEndpointAddressIdentity otherChannelFactoryEndpointAddressHeaders);
WCFContractsIUser otherUser = otherChannelFactoryCreateChannel();
otherUserInsert();
ConsoleWriteLine( 調用服務成功/n);
/*方案二結束*/
}
附帶身份驗證
在VS工具的命令行中
()添加證書
makecert sr LocalMachine ss My a sha n CN=MyWCFServer sky exchange pe
()將證書設置成可信任的
certmgr add r LocalMachine s My c n MyWCFServer s TrustedPeople
From:http://tw.wingwit.com/Article/program/net/201311/13011.html