Il TcpClient è un interessante wrapper per le connessione con Socket. A me poi piace incapsulare lo stream (vedere GetStream) in StreamReader e StreamWriter per poter facilmente leggere e scrivere sul canale.Questo potrebbe obbligare - a prima vista - a rinunciare alla ricezione asyncrona dei dati (vedere BeginReceive) costrigendo a implementare la classica procedura che in thread parallelo consuma il canale a colpi di ReadLine. Quando poi arriva il "null" potrebbe essere il caso di chiudere la conversaizone...
La soluzione del "BeginReceive" potrebbe invece coinvolgerci in complessi, arzigogolati e un pò poco leggibili algoritmi per gestione di buffer riempiti asyncronamente... (un esempio è qui ben descritto "Asynchronous Server Socket using C#").
Oggi ho provato una solzuzione che unisce le due cose, la leggerezza del BeginReceive per attivare il codice solo quando arrivano dati e la praticità dei StreamReader e StreamWriter per il consumo del canale. La "BeginReceive" permette infatti di effettuare anche delle operazioni di Peek ("Reads data without changing the state of the reader or the character source. Returns data without actually reading it from the input stream").
Ecco un esempio che tralascia tutti i fronzoli di controllo sullo stato della socket, gestione delle eccezioni etc...
private void BeginReceive()
{
byte[] dummy = new byte[1];
this.myTcpClient.Client.BeginReceive(dummy, 0, dummy.Length, SocketFlags.Peek, new AsyncCallback(BeginReceiveCallback), null);
}
//...
private void BeginReceiveCallback(IAsyncResult asyncResult)
{
this.myTcpClient.Client.EndReceive(asyncResult);
string commandLine = this.myStreamRaeder.ReadLine();
//...
BeginReceive();
}
Una soluzione che potrebbe non essere universale ma che mi sembra ben si sposi con i protocolli classici di rete che si basano sul concetto delle linee di comando...
posted @ martedì 27 giugno 2006 23:39