lunes, 21 de marzo de 2011

Referencias acerca del uso del Garbage Collector en .NET

Buscando referencias en cuanto al uso de los destructores en C# me encontré estos fragmentos del libro Advanced C# Programming de Paul Kimmel donde en el capítulo 1 pag 18 habla acerca de la destrucción no determinística y Garbage Collector, fragmento que copio tal cuál se encuentra en el libro:


C# uses non-deterministic destruction. The CLR implements a garbage collector that cleans up memory when objects are no longer used. This means that you don’t have to worry as much about destructors in C# as you do in C++ or Delphi.
The garbage collector will call the destructor for your objects when they are no longer needed. The destructor will call any Finalize method. You can force garbage collection by calling GC.Collect, but this is not a recommended process. The garbage collector suspends any running threads, which can cause performance problems. Besides, the garbage collector will do a good job of determining when to run.


De nuevo en el en el capítulo 3 pag 76, recalca la importancia de que no es una buena práctica, fragmento que copio tal cuál se encuentra en el libro



Control Dispose Methods C# is a .NET language. I state the obvious as a way to segue into a subject that may not be obvios. Languages like Object Pascal or C++ use deterministic construction and destruction. This means that the programmer is responsible for both creating and destroying objects.
.NET employs non-deterministic destruction.This means that the programmer is not responsible for destroying objects.The gargabe collector will clean up objects for you. As a result, you will write code that invokes the new operator, but there is no equivalent free operator.
NOTE: You can invoke the garbage collector explicitly by calling GC.Collect, but this is not a recommended practice.


Aunque la biblioteca de la universidad tiene la edición 2002 y no sé si en las ediciones actuales haya cambiado, considero que es interesante lo que menciona además que un amigo y compañero de trabajo me pregunto hace algunos años si era posible invocar a voluntad el Garbage Collector a lo cual respondí por lógica que sí porque ya había visto la clase System.GC y algo había leído algo al respecto pero en ese momento no sabía bien acerca de sus implicaciones y no había recordado la fuente.


domingo, 20 de marzo de 2011

Uso de Destructores en C#

En lenguajes orientados a objetos como C#,C++ o Java los objetos tienen un ciclo de vida el cual inicia cuando se crea el objeto mediante un constructor y acaba cuando se termina el objeto mediante un destructor.
Por ejemplo con la palabra reservada new, llamamos al constructor de un
objeto del tipo router:



El uso de constructores es igual en C# como lo es en C++ y Java, donde sino especificamos el constructor, el compilador se encarga de crearlo ya que una de sus responsabilidades es la llamada a un constructor el cual como un estándar tomado de C++ el constructor tiene el mismo nombre que la clase.
De igual forma la clase puede tener el constructor predeterminado sin argumentos, como un constructor personalizado, por ejemplo en el siguiente código:


En C# a diferencia de C++ existe el Garbage Collector (recolector de basura) que se encarga de destruir los objetos que fueron creados y ya no son utilizados, por lo que el programador no es responsable de liberar recursos asignando un destructor a cada objeto.


Sin embargo hay casos en C# donde los destructores son necesarios para objetos que hacen uso de recursos no administrados (unmanaged resources) como las conexiones hacia las bases de datos o el uso de archivos.
Los destructores a diferencia de los constructores no se heredan, no pueden recibir parámetros y no pueden sobrescribirse.
La sintaxis de un destructor es con el mismo nombre que el constructor solo se agrega una ~ como prefijo, como se muestra en el siguiente código:



A continuación el programa principal para ejemplificar los destructores

En este ejemplo el código dentro del destructor imprime un mensaje en la consola lo cual es algo trivial, esto es importante ya que en la mayoría de la documentación que hablan acerca de destructores en C# señalan que deben usarse con extremo cuidado.Hay ciertas reglas acerca de su uso:



  1. Se debe tener presente es nunca utilizar destructores en managed code (código manejado) ya que representa un problema de desempeño para el garbage collector, ya que a diferencia de C++ el objeto no es destruido inmediatamente cuando es ejecutado el destructor.

  2. En lugar de destructores utilizar Close() o Dispose().

  3. NUNCA poner código en el destructor que realice cambios críticos al ambiente o bien código que utilice recursos, es decir los destructores se usaron para liberar no para utilizar.

  4. No se debe hacer referencia a otros objetos dentro del destructor.

  5. Nunca llames a un constructor de forma directa, el garbage collector
    lo invoca de forma automática, si se requiere liberar recursos de forma
    determinística lo recomendable es usar la interfaz IDisposable.



Es posible invocar y controlar el Garbage Collector vía los métodos estáticos de la clase System.GC, pero no es recomendable ya que se activa para todas las aplicaciones que utilicen recursos en ese momento no únicamente para la aplicación que lo invoco, además que debemos de conocer los métodos no determinísticos para la liberación de memoria.
A continuación la salida del programa


domingo, 27 de febrero de 2011

Cambiando la resolución de pantalla de forma permanente en OpenSuse 11.3

Pues teniendo desde hace un par de meses OpenSuse 11.3 en mí nueva portátil (Dell Inspiron 14), algo que ya había leído pero no había hecho era cambiar la resolución de la pantalla de forma permanente.
Ya que de forma predeterminada el sistema establecía la resolución 1366x768 resolución que para mostrar ciertas gráficas en proyectores no era apropiada, por lo que siempre cambiaba la resolución de forma manual a una resolución estándar de 1024x768, algo que en versiones anteriores de OpenSuse se realizaba con Sax2 y se conservaba después de reiniciar o apagar el equipo cosa que en esta versión no ocurre.


Leyendo en la documentación de OpenSuse encuentro que esta versión no incluye Sax2 ni sus derivados como (Sax2-vesa), por lo que ese cambio debe hacerse de forma programática.


El procedimiento se describe en este enlace .
A continuación pongo algunas anotaciones con imágnes en caso de que el enlace/post cambie y para que tenga manera de recordarlo.



  1. Como root cambiamos al directorio /etc/X11/xorg.conf.d/
    # cd /etc/X11/xorg.conf.d/

  2. Sacamos una copia de seguridad del archivo 50-screen.conf
    # cp 50-screen.conf 50-screen.conf.bak


  3. Vemos las resoluciones soportadas en el menú "Preferencias del sistema" del inicio de KDE.



  4. Editamos el archivo, agregando las siguientes líneas y colocando en primer lugar la resolución que necesitamos de forma permanente.
    # vi 50-screen.conf
    Section "Screen"
    Identifier "Default Screen"
    Device "Default Device"

    ##Doesn't help for radeon/radeonhd drivers;use magic in
    ##50-device.conf instead
    Monitor "Default Monitor"

    SubSection "Display"
    modes "1024x768" "800x600" "640x480"
    EndSubSection

    EndSection



  5. Reiniciamos el equipo para probar el cambio.

Diferencias entre C# DateTime.Now y DateTime.Today

Hoy por la tarde haciendo un programa para enviar mensajes hacia un servidor me salió un error simple que después de cierto tiempo pude resolverlo y se debió más a un bloqueo de mi memoria que ha otro factor.
Resulta que uno de los requisitos en el programa era enviar como título del mensaje fecha, hora, minutos y segundos en los que cada mensaje se había generado.
Básicamente existía una clase mensaje con una propiedad DateCreated como en el siguiente código:



Al crear el mensaje, el programa debía notificar con un aviso, indicando fecha, hora, minutos y segundos, algo así como lo siguiente:


“Mensaje recibido 24-02-2011 a las 22:04:12”

Sin embargo el mensaje lo notificaba de la siguiente forma:

“Mensaje recibido 24-02-2011 a las 22:04:00 ”

El código principal era más o menos asi


Al revisar el código descubrí que al usar la estructura DateTime utilice la propiedad Today en lugar de la propiedadNow .
Ambas propiedades obtienen el valor de la fecha actual, la diferencia es que en Today la parte correspondiente al tiempo se establece en 00:00:00.


al cambiar la propiedad DateCreated como en la siguiente línea:


public DateTime DateCreated
{
get{ return DateTime.Now;}
}

El problema se soluciono y aquí el resultado.

viernes, 14 de enero de 2011

Operadores a nivel de bits en C# (bitwise operators)

Además de los operadores condicionales lógicos y de relación C# cuenta con operadores a nivel de bits (bitwise operators o logical operators) que permiten realizar operaciones con las representaciones binarias de las variables que internamente utiliza la computadora, esto es útil en ciertos casos donde se requiere interactuar directamente con el hardware o utilizar una variable entera como un arreglo de bits donde por ejemplo un tipo short representaría un arreglo de bits con una longitud de 16 valores y cada bit podría ser utilizado como si fuera un valor booleano 1 igual true y 0 igual a false.

Los tipos de datos donde usualmente aplican estos operadores son: los numéricos y las enumeraciones.

La siguiente tabla muestra los tipos numéricos, su longitud en bytes y su valor en decimal.


Así por ejemplo si tenemos valores decimales representados en variables byte (8 bits hasta 255 en decimal)

byte a = 22;
byte b = 33;

Internamente su representación en binario es:

22 = 00010110
33 = 00100001

si utilizamos variables de tipo short (16 bits hasta 65,535)

short c = 666;
short d = 6666;

su representación en binario es:

666 = 00000010 10011010
6666 = 00011010 00001010

Así con cada tipo numérico siempre agrupando las cadenas de bits de 8 en 8.
La siguiente tabla muestra los operadores bitwise, su significado y su resultado.


A continuación un ejemplo de la utilización de estos operadores con enteros, este programa tiene 3 clases:

  1. BitwiseGUI.class: Contiene el código para las interacciones del usuario con el programa, como el menú,la pausa y la impresión del resultado.
  2. BitwiseMath.class: Contiene las operaciones unarias y binarias de los operadores.
  3. MainClass.class: Es el programa principal en donde se evalua la opción ingresada por el usuario.


Compilamos y ejecutamos el programa desde Monodevelop

Al ejecutarlo veremos los siguientes resultados:


Otro uso común de estos operadores esta en las enumeraciones como en el caso de los valores de las enumeraciones FileMode y FileAccess del siguiente código.


    
FileStream outStream = new FileStream("log.txt",FileMode.Append | FileMode.Create,
FileAccess.Read | FileAccess.Write,FileShare.Read);
StreamWriter sw = new StreamWriter(outStream);
sw.WriteLine("Archivo de log");
sw.Close();

martes, 4 de enero de 2011

Notas acerca de los elementos de la comunicación en redes de datos

La comunicación comienza con un mensaje o información que debe enviarse de un individuo o de un dispositivo a otro. Aunque hay muchos métodos de comunicación la comunicación tiene básicamente tres partes, que son:



  • La fuente del mensaje o el emisor que pueden ser personas o dispositivos.

  • El destino del mensaje o el receptor quien recibe el mensaje y lo interpreta.

  • El canal que consiste del medio en el cual se transmite el mensaje.


En el caso de las redes de datos en vez de enviar todo el mensaje por el canal y esperar hasta que el receptor lo interprete de principio a fin, se realiza una estrategia llamada segmentación donde el mensaje se divide en pequeñas partes y cada una de esas partes es enviada al emisor hasta completar el mensaje, esto trae dos ventajas, la primera es que se pueden enviar diferentes mensajes por el mismo canal ya que se pueden intercalar las partes de diferentes mensajes dentro del canal evitando la saturación por un mensaje de tamaño considerable y la segunda es que no todos los mensajes van desde la misma fuente al mismo destino si una vía dentro del canal se congestiona o se cae, las partes pueden tomar vías alternas y además si algunas partes del mensaje no llegan a su destino esas partes pueden ser retransmitidas.

Aunque la segmentación le agrega mayor complejidad y consumo de tiempo al proceso de la comunicación en las redes de datos esto asegura el correcto envió y recepción de mensajes. Varios tipos de dispositivos a través de la red participan en este proceso, los componentes visibles y los componentes no visibles. Los componentes visibles de la red de datos son los elementos de hardware que participan en la red como laptops, PC's, el cableado y los switches y los elementos no visibles se refiere al software como los procesos de servicios de los programas de comunicación que se ejecutan en los dispositivos de red, estos servicios responden a una petición como los servicios de emaill o de web, aunque son menos evidentes son críticos para la operación de las redes ya que se encargan de la respuesta a las solicitudes de los mensajes.

Los dispositivos de red que están cerca del usuario se conocen como dispositivos finales estos dispositivos son la interfaz entre la red humana y la red de comunicación de datos. En el contexto de las redes de datos un dispositivo final está referido como un host, ya que es tanto como el emisor o el receptor de los mensajes transmitidos a través de la red, un host se distingue de otro dentro de la red mediante su dirección. En las redes modernas un host actúa tanto como cliente, como servidor o como ambas cosas esto lo determina el tipo de software que tenga instalado.

Por ejemplo si una PC tiene instalado un servidor de correo electrónico (como postfix) y de hosteo de páginas Web (como apache) entonces está habilitada como servidor tanto de correo electrónico como de páginas web y sí tiene además instalado software de cliente de correo (como thunderbird) y de navegador web (como firefox) entonces también está habilitada como cliente de correo electrónico y de páginas web.

Además de los dispositivos finales en la red de datos existen los dispositivos intermediarios que proporcionan la conectividad y todo el trabajo para asegurarse que los datos fluyan dentro de la red. Estos dispositivos conectan los hosts a la red y la red o redes de hosts para formar una interred o internetwork como es el caso de Internet, ejemplos de dispositivos intermediarios son:



  • Dispositivos de acceso a la red (Hubs,switches, wireless access point)

  • Dispositivos interred (routers)

  • Servidores de comunicación y los modems

  • Dispositivos de seguridad (firewalls)


Estos dispositivos usan la dirección de host (host address) en conjunción con la información de las redes interconectadas para determinar la trayectoria de los mensajes dentro de la red, los procesos que se ejecutan en estos dispositivos realizan las siguientes funciones:



  • Generan y retransmiten las señales de datos.

  • Mantienen la información acerca de las rutas existentes en la red.

  • Notifican a otros dispositivos de los errores o de las fallas de comunicación.

  • Si hay un error de enlace enviar la señal en rutas alternas.

  • Clasifican los mensajes acorde a las prioridades de QoS.

  • Permite o rechazan el flujo de datos basados en la configuración de seguridad.


Las redes modernas usan principalmente tres tipos de medio para la interconexión de dispositivos, esos medios son:



  • Cables metálicos

  • Cables de fibra óptica

  • La transmisión por ondas (wireless)


La codificación de la señal es diferente en cada tipo de medio, en los medios metálicos la señal es codificada mediante impulsos eléctricos, en los medios de fibra óptica es codificada como impulsos de luz infrarroja o blanca y en la transmisión wireless es codificada como patrones de ondas electromagnéticas.


martes, 30 de noviembre de 2010

Notas acerca de direcciones IP y la dirección IP en .NET

Las direcciones IP se dividen en tres clases generales (A, B, C) y dos especializadas que son utilizadas para propósitos experimentales (D, E). Las direcciones IP se representan por cuatro octetos u ocho bits, separados por puntos, así como la dirección MAC nos proporciona identificación, la dirección IP nos da ubicación.

Cada dirección IP se compone de dos campos un campo de red y un campo de host. El tamaño de cada uno de esos campos varía según la clase:
Para la clase A tenemos el primer octeto para identificar la red y los restantes tres para identificar al host.
Para la clase B tenemos los dos primeros octetos para identificar la red y los dos restantes para identificar al host.
Para la clase C tenemos los tres primeros octetos para identificar al host y el último octeto para identificar al host.
El primer octeto en decimal siempre nos indica la clase a la que pertenece una red, dependiendo de su valor en decimal dentro de los siguientes rangos:


  • 0 a 127 es clase A

  • 128 a 191 es clase B

  • 192 a 223 es clase C


Aquí si observamos el inicio del rango es par y el final es impar.
En la clase A, la dirección IP 127.0.0.1 se reserva como dirección de loopback.
Existen además tipos reservados de IP como por ejemplo si los octetos de host son puestos en 0 (cero) esa dirección IP identifica a la red o si todos los octetos de host son puestos en 1 o 255 en decimal esa dirección IP es una dirección IP de Broadcast.

Una manera de identificar los tipos de red es buscar la posición del bit 0 (cero) dentro del primer octeto, la reglas son:
Si el primer bit es 0 (cero) la dirección es clase A, si el segundo bit es 0 (cero) la dirección es clase B, si el tercer bit es 0 (cero) entonces es clase C. Como en el siguiente esquema:


clase A | 0 1 1 1 1 1 1 1
---------+-----------------
clase B | 1 0 1 1 1 1 1 1
---------+----------------
clase C | 1 1 0 1 1 1 1 1


IP local en .NET

.Net tiene diversas clases dentro del ensamblado System.Net para el manejo de direcciones IP mostraremos el uso básico de esas clases para obtener la dirección o las direcciones IP de la máquina en donde se ejecute el siguiente listado.

Para acceder a las clases de red, primeramente hacemos referencia a los ensamblados


using System.Net;
using System.Net.Sockets;

En la siguiente línea

IPHostEntry ipinfo = Dns.GetHostByName(Dns.GetHostName());

Utilizamos el método GetHostByName de la clase Dns el cual nos devuelve un objeto IPHostEntry del cual utilizamos la propiedad AddressList que es una lista de objetos del tipo IPAddress que representa cada IP de la máquina en caso de tener más de una interface de red y que recorremos con un ciclo utilizando el método GetAddressBytes() para obtener los octetos como un arreglo.

foreach(IPAddress ip in ipinfo.AddressList){
byte[] b = ip.GetAddressBytes();
}

Por último utilizamos las propiedades estáticas IPAddress.Loopback y IPAddress.Broadcast para imprimir la dirección Loopback y de Broadcast respectivamente.
Al compilar y ejecutar el programa obtendremos algo similar a lo que se muestra en la siguiente imagen: