Around and About .NET World

Il blog di Marco Minerva
posts - 1671, comments - 2232, trackbacks - 2135

My Links

News

Contattami su Live Messenger:


MCTS: Windows, Web, Distributed Applications & SQL Server

MCPD: Enterprise Applications

Tag Cloud

Archives

Post Categories

Links

sabato 29 dicembre 2007

Applicazioni Peer-to-Peer in .NET 3.5

Contrordine... Mi lascio un appunto qui, così l'anno nuovo so già a cosa dovrò lavorare Smile.

Mi sto riferendo ai nuovi oggetti forniti dal .NET Framework 3.5 per la gestione di applicazioni Peer-to-Peer: in particolare, PeerName, PeerNameRegistration e PeerNameResolver, contenuti nel namespace System.Net.PeerToPeer. Grazie ad essi, realizzare applicazioni Peer-to-Peer è di una semplicità sconcertante. Ad esempio, il seguente codice pubblica un nuovo peer:

1 // Creates a secured PeerName. 2 PeerName peerName = new PeerName("MyPeerNode", PeerNameType.Secured); 3 4 PeerNameRegistration pnReg = new PeerNameRegistration(peerName, 4567, Cloud.Global); 5 pnReg.UseAutoEndPointSelection = true; 6 pnReg.Comment = "up to 39 unicode char comment"; 7 pnReg.Data = Encoding.UTF8.GetBytes("A data blob up to 4K associated with the name"); 8 9 //Starting the registration means the name is published for other peers to resolve. 10 pnReg.Start(); 11 12 Console.WriteLine("Registration of Peer Name: {0} complete.", peerName.ToString()); 13 14 Console.WriteLine("Press any key to stop the registration and close the program"); 15 Console.ReadKey(); 16 17 pnReg.Stop();

Il codice è abbastanza autoesplicativo. L'unica nota la merita l'istruzione 4, con cui si crea l'oggetto che si occupa di effettuare la registrazione vera e propria del peer: utilizzando il parametro Cluod.Global, si indica al sistema che il peer deve essere visibile globalmente (ovvero su tutta Internet).

Il discovery dei peer è altrettanto semplice:

 

1 // Create a resolver object to resolve a peername. 2 PeerNameResolver resolver = new PeerNameResolver(); 3 PeerName peerName = new PeerName("MyPeerNode", PeerNameType.Secured); 4 // Resolve the PeerName - this is a network operation and will 5 // block until the resolve request is completed. 6 PeerNameRecordCollection results = resolver.Resolve(peerName, Cloud.Global); 7 8 // Show the data returned by the resolve operation. 9 Console.WriteLine("Records from resolution of PeerName: {0}", results.Count); 10 Console.WriteLine(); 11 int count = 1; 12 foreach (PeerNameRecord record in results) 13 { 14 Console.WriteLine("Record #{0} results...", count); 15 16 Console.WriteLine("Comment:"); 17 if (record.Comment != null) 18 Console.WriteLine(record.Comment); 19 20 Console.WriteLine("Data:"); 21 if (record.Data != null) 22 Console.WriteLine(Encoding.UTF8.GetString(record.Data)); 23 24 Console.WriteLine("Endpoints:"); 25 foreach (IPEndPoint endpoint in record.EndPointCollection) 26 Console.WriteLine("\t Endpoint: {0}", endpoint.Address); 27 28 count++; 29 } 30

In questo caso, l'istruzione fondamentale è quella alla riga 6, con cui si effettua il discovery: anche stavolta, si utilizza Cloud.Global, indicando che si vuole fare una ricerca globale (altrimenti sarebbe limitata ai peer registrati nella propria sottorete). Nell'esempio, il discovery è effettuato in maniera sincrona, ma sono disponibili anche i metodi e gli eventi per realizzare il tutto in modo asincrono.

Naturalmente questo è solo il punto di partenza. Ci sarebbe molto da dire su come funziona il supporto al Peer-to-Peer in .NET, su cosa avviene "dietro le quinte" quando si registra un peer e quando si avvia il discovery... Ma di questo parleremo l'anno nuovo Tongue out... Adesso vi lascio veramente ai festeggiamenti... A presto, miei cari 25 lettori!

Technorati tags: , ,

posted @ lunedì 1 gennaio 0001 00:00 | Feedback (2) | Filed Under [ C# Orcas & .NET 3.5 ]

Buon anno!

Con quello che presumibilmente sarà il mio ultimo post del 2007, faccio a tutti i migliori

AUGURI DI BUON ANNO!

Technorati tags:

posted @ lunedì 1 gennaio 0001 00:00 | Feedback (2) | Filed Under [ Tutto & Oltre :-) ]

Effettuare il Join di due DataTable

Qualche giorno fa ho avuto la necessità di effettuare il join di due DataTable, risultato di interrogazioni su due database differenti, per produrre un unico DataTable da mostrare in un controllo DataGridView. Le due tabelle dovevano essere unite sulla base di un campo ID, secondo l'usuale relazione di chiave-chiave esterna. Mi sono così definito una procedura per eseguire l'operazione:

private void Join(DataTable mainTable, string mainRowField, string parentRowField, DataRelation relation) { //Controlla se la tabella contiene la colonna in cui aggiungere i risultati del join. if (!mainTable.Columns.Contains(mainRowField)) mainTable.Columns.Add(mainRowField); foreach (DataRow row in mainTable.Rows) row[mainRowField] = row.GetParentRow(relation)[parentRowField].ToString(); }

Il suo utilizzo è molto semplice. Supponiamo di avere le seguenti DataTable:

DataTable dt1 = new DataTable(); dt1.Columns.Add("NomeUtente"); dt1.Columns.Add("IDCitta"); dt1.Rows.Add(new object[] { "Marco", 12 }); dt1.Rows.Add(new object[] { "Andrea", 12 }); dt1.Rows.Add(new object[] { "Pippo", 13 }); DataTable dt2 = new DataTable(); dt2.Columns.Add("NomeCitta"); dt2.Columns.Add("IDCitta"); dt2.Rows.Add(new object[] { "Taggia", 12 }); dt2.Rows.Add(new object[] { "Sanremo", 13 }); dt2.Rows.Add(new object[] { "Poggibonsi", 14 });

Come è facile intuire, esse dovrebbero essere unite sulla base del valore del campo IDCitta. La prima cosa da fare è inserire queste tabelle in un DataSet e definire una DataRelation tra di esse:

DataSet ds = new DataSet(); ds.Tables.AddRange(new DataTable[] { dt1, dt2 }); ds.Relations.Add("Origine", dt2.Columns["IDCitta"], dt1.Columns["IDCitta"], false);

La relazione è tra la chiave primaria IDCitta di dt2 e la chiave esterna IDCitta in dt1. A questo punto si può finalmente richiamare il metodo Join:

Join(dt1, "Citta", "NomeCitta", ds.Relations[0]);

Dove:

  • dt1 è la tabella che si vuole "arricchire" con la giunzione;
  • Citta è il nome della colonna di dt1 in cui si vuole aggiungere il risultato della giunzione (se non esiste, verrà creata automaticamente);
  • NomeCitta è il campo della tabella in giunzione i cui valori verranno copiati nella colonna Citta della prima tabella;
  • ds.Relations[0] è il riferimento alla DataRelation da utilizzare per trovare i record in giunzione.

Tutto qui Smile

Technorati Tag: ,,,

posted @ lunedì 1 gennaio 0001 00:00 | Feedback (1) | Filed Under [ C# ADO .NET & SQL ]

Determinare quando è disponibile una connessione a Internet

Ormai sono lanciato nella realizzazione di classi di supporto per la gestione della rete. Dopo NetworkChange2, oggi è la volta di una classe che consente di sapere se il PC è collegato a Internet oppure no, nonché di ricevere notifiche se lo stato della connessione cambia:

1 using System; 2 using System.ComponentModel; 3 using System.Threading; 4 using System.Net; 5 6 namespace System.Net.NetworkInformation 7 { 8 public delegate void InternetAvailabilityChangedEventHandler(object sender, InternetAvailabilityEventArgs e); 9 10 public static class NetworkMonitor 11 { 12 private const string HOST = "http://www.microsoft.com"; 13 14 private static AsyncOperation operation; 15 private static SendOrPostCallback internetAvailabilityCallback; 16 private static bool internetAvailable; 17 18 private static Timer checkConnection; 19 private const int CHECK_CONNECTION_TIMEOUT = 5000; 20 21 public static event InternetAvailabilityChangedEventHandler InternetAvailabilityChanged; 22 23 static NetworkMonitor() 24 { 25 internetAvailable = false; 26 27 operation = AsyncOperationManager.CreateOperation(null); 28 internetAvailabilityCallback = new SendOrPostCallback(InternetAvailabilityHandler); 29 30 //Attiva il timer che controlla la disponibilità della connessione. 31 checkConnection = new Timer(new TimerCallback(IsConnectionAvailable), null, 1, CHECK_CONNECTION_TIMEOUT); 32 } 33 34 public static bool IsConnectionAvailable() 35 { 36 HttpWebRequest request = null; 37 HttpWebResponse response = null; 38 bool isAvailable = false; 39 40 try 41 { 42 request = (HttpWebRequest)HttpWebRequest.Create(HOST); 43 response = (HttpWebResponse)request.GetResponse(); 44 45 if (response.StatusCode == HttpStatusCode.OK) 46 { 47 // HTTP = 200 - Internet connection available, server online 48 isAvailable = true; 49 } 50 } 51 catch (WebException) 52 { } 53 finally 54 { 55 try 56 { 57 if (response != null) 58 response.Close(); 59 } 60 catch { } 61 } 62 63 return isAvailable; 64 } 65 66 private static void IsConnectionAvailable(object stateInfo) 67 { 68 checkConnection.Change(Timeout.Infinite, Timeout.Infinite); 69 70 bool isAvailable = IsConnectionAvailable(); 71 if (isAvailable != internetAvailable) 72 { 73 internetAvailable = isAvailable; 74 operation.Post(internetAvailabilityCallback, new InternetAvailabilityEventArgs(isAvailable)); 75 } 76 77 checkConnection.Change(CHECK_CONNECTION_TIMEOUT, CHECK_CONNECTION_TIMEOUT); 78 } 79 80 private static void InternetAvailabilityHandler(object stateInfo) 81 { 82 if (InternetAvailabilityChanged != null) 83 InternetAvailabilityChanged(null, (InternetAvailabilityEventArgs)stateInfo); 84 } 85 } 86 87 public class InternetAvailabilityEventArgs : EventArgs 88 { 89 private bool isAvailable; 90 public bool IsAvailable 91 { 92 get { return isAvailable; } 93 } 94 95 public InternetAvailabilityEventArgs(bool isAvailable) 96 { 97 this.isAvailable = isAvailable; 98 } 99 } 100 }

In estrema sintesi, questa classe cerca di effettuare una richiesta HTTP (righe 42-43) e, in base al messaggio di risposta, determina se la connessione al Web è disponibile oppure no. Questo non è l'unico metodo possibile, ad esempio un'alternativa si basa sull'utilizzo dell'API di Windows InternetGetConnectedState, ma dove possibile preferisco rimanere nel "mondo managed".

Technorati Tag: ,,

posted @ lunedì 1 gennaio 0001 00:00 | Feedback (0) | Filed Under [ C# ]

Powered by:
Powered By Subtext Powered By ASP.NET