Sunucu-istemci modelini kullanan bir uygulama geliştiriyorsanız sunucunun hizmet noktası bilgilerinin (FQDN, IP numarası, protokol, port numarası vs) sık sık değişmesi çok can sıkıcı bir durum oluşturabilir. Zira istemci tarafındaki kaynak kodu veya bu bilgileri bir dosyada tutuyorsanız bu dosyayı güncellenmeniz gerekecektir. .NET Compact Framwork de ConfigurationManager sınıfının bulunmayışı durumu daha da can sıkıcı bir hale getirebilir. Bu makalemizde bu iki sorunu aynı anda çözecek bir yapı geliştireceğiz.
Bu dönem boyunca (2010 bahar) Mobile and Wireless Systema Lab dersi kapsamında mobil sistemler için uygulama geliştiriyorduk. Benim ekibim Windows Mobile 6.5 üzerinde çalışıyordu, gerçi dönem başında Google Android platformu için “Text-to-speech” ( “konuşabilen” diye tercüme edelim J ) bir RSS okuyucu geliştirdiysek de asıl projemiz Windows Mobil sistemler içindi. Geliştirme esnasında sunucu tarafı uygulamayı bir çok daha Azure Cloud Computing sistemi ile yerel Windows Server arasında defalarca taşımak zorunda kaldık. Bu durum istemci tarafında çok sorun oluşturmaya başlayınca istemcilerin bu durumdan etkilenmemesi sağlayacak basit bir çözüm geliştirdim.
Öncellikle Windows Mobil sistem için bir konfigürasyon yöneticisi oluşturacağız. Bu yönetici sunucu tarafı hizmet noktası bilgilerini gerekli yerlerden okuyup hafızada saklı tutacak uygulama içindeki diğer modüllerden/katmanlardan herhangi bir ayarın detayları istediğinde, mesela sunucunun ip adresi, bu bilgileri sunacak.
Konfigürasyon yöneticisi bu işlevi üç aşamada gerçekleştirecek:
Adım 1: Yerel konfigürasyon dosyasının okunması:
Bu aşamada konfigürasyon yöneticisi yerel dosyadan hizmet bilgilerinin (serviceSettings) saklandığı dosyanın adresini okuyacak.
string appPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
string configFile = Path.Combine(appPath, "Settings.config");
//make sure that the local setting file exits
if (!File.Exists(configFile))
{
throw new FileNotFoundException(
string.Format("Application configuration file '{0}' not found.",
configFile));
}
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(configFile);
XmlNodeList nodeList = xmlDocument.GetElementsByTagName("serviceSettings");
Settings = new NameValueCollection();
foreach (XmlNode node in nodeList)
foreach (XmlNode key in node.ChildNodes)
Settings.Add(key.Attributes["key"].Value.Trim(),
key.Attributes["value"].Value.Trim());
Örnek bir ayar dosyası şu şekilde olabilir:
Settings.config:
<?xml version="1.0"?>
<configuration>
<serviceSettings>
<add key="configurationFile" value="http://pages.cs.wisc.edu/~ilikhan/vnote/service.config" />
</serviceSettings>
</configuration>
Adım 2: Uzak (remote) konfigürasyon dosyasının okunması:
Bu aşamada hizmet bilgilerin saklandığı dosyaya erişip gerekli bilgileri okuyoruz.
xmlDocument = new XmlDocument();
string serviceConfigFile = Settings["configurationFile"];
//determine location of file ( local or remote)
if (serviceConfigFile.StartsWith("http",
StringComparison.InvariantCultureIgnoreCase) == true)
//check the internet connectivity
if (Program.isDataConnectionAvailable)
Stream configFileStream = GetFileFromWeb(serviceConfigFile);
xmlDocument.Load(configFileStream);
else
xmlDocument.Load(serviceConfigFile);
nodeList = xmlDocument.GetElementsByTagName("servicePoint");
Örnek bir hizmet bilgileri ayar dosyası şu şekilde olabilir:
<?xml version="1.0" encoding="utf-8" ?>
<servicePoint>
<add key="remoteAddress" value="vnote.cloudapp.net" />
<add key="IPAddress" value="" />
<add key="protocol" value="tcp" />
<add key="port" value="14500" />
</servicePoint>
Adım 3: Son olarak gerekli bilgiler üzerinden sunucu tarafındaki uygulamaya bağlanabiliriz
Örnek bir kullanım şu şekilde olabilir:
public static void PrepareConnectionSettings()
try
string hostNameOrAddress =
MobileConfigManager.Settings["remoteAddress"];
if (hostNameOrAddress == string.Empty ||
hostNameOrAddress == null)
szIPSelected = MobileConfigManager.Settings["IPAddress"];
IPHostEntry ipE = Dns.GetHostEntry(hostNameOrAddress);
IPAddress[] IpA = ipE.AddressList;
szIPSelected = IpA[0].ToString();
szPort = MobileConfigManager.Settings["port"];
alPort = System.Convert.ToInt16(szPort, 10);
System.Net.IPAddress remoteIPAddress =
System.Net.IPAddress.Parse(szIPSelected);
remoteEndPoint =
new System.Net.IPEndPoint(remoteIPAddress, alPort);
catch
{ }
Yukarıdaki kod konfigürasyon yöneticisinde sunucu adını (FQDN) istiyor, eğer sunucu adı belirtilmişse DNS sorgusu yapıp IP Adresini tespit ediyor. Eğer sunucu adı belirtilmemiş ise konfigürasyon yöneticisinden sunucunun IP adresini vermesini istiyor. Gerekli bilgiler elde edilince bağlantıda kullanılacak uç noktayı oluşturuyor.
Oluşturduğumuz sınıfın kaynak kodunun tamamı aşağıdaki gibi olabilir:
public static class MobileConfigManager
public static NameValueCollection Settings;
public static void InitializeConfiguration()
//string appPath = Directory.GetCurrentDirectory();
string.Format("Application configuration file '{0}' not found.", configFile));
if (serviceConfigFile.StartsWith("http", StringComparison.InvariantCultureIgnoreCase) == true)
Settings.Add(key.Attributes["key"].Value.Trim(), key.Attributes["value"].Value.Trim());
}//end
private static Stream GetFileFromWeb( string configFileURI)
// Begin the WebRequest to the desired configuration file
System.Net.WebRequest webRequest = System.Net.WebRequest.Create( configFileURI );
HttpWebRequest request = webRequest as HttpWebRequest;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Convert the file into an XML document
System.IO.Stream configFileStream = response.GetResponseStream();
return configFileStream;
}//end of class
Tabi bu işlemlerin yerine getirilebilmesi için program açılır açılmaz konfigürasyon yöneticisinin çağrılması gerekmektedir.
MobileConfigManager.InitializeConfiguration();
Bu işin de otomatik yapılmasını istiyorsak InitializeConfiguration() çağrısını bu sınıf için tanımlanan constructor gövdesinde yapabiliriz. Çünkü static bir sınıf tanımladığımız için uygulama çalıştırıldığında bu sınıf otomatik olarak sisteme yüklenecektir. Fakat uzak ayar dosyasının (remote settings) bir web request ile erişilmeye çalıştığımda garip bir şekilde sistemin çok yavaş cevap verdiğini fark ettim. Bu nedenle contructor içinden bu işlemleri yapmak yerine ma programın başlangıcında manuel olatak çağırmak zorunda kaldım. Benim kullandığım sistem Windows Mobile 6.5, ve Compact Framework 3.5 yüklü. Farklı sürümlerde aynı sorunun olup olmadığını test etmedim.
Özet olarak bu yazımızda mobil sistemler için nasıl basit bir konfigürasyon yöneticisi geliştirmeğimizi, ayrıca istemci tarafında herhangi bir değişiklik yapmadan nasıl sunucumuzu taşıyabileceğimizi öğrendik.
Faydalı olması ümidiyle…
Özcan İLİKHAN
PhD Student Department of Computer Sciences University of Wisconsin-Madison http://pages.cs.wisc.edu/~ilikhan