Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Monday, December 3, 2007

Como funciona HTTP como Separador de Mensajes TCP

Tal como ya había comentado en un post anterior, TCP es un Protocolo de Control de Flujo de Datos, no de Mensaje de Datos por lo que es necesario implementar un separador de Mensajes sobre TCP. ¿Qué exactamente Hace un Separador de Mensajes? Un separador de Mensajes es un conjunto de reglas que se aplican sobre la transmisión de datos para saber de que parte de que flujos comienzan o finalizan los mensajes, casi siempre el Separador de Mensajes se implementa con un Encabezado y un Contenido donde una de las múltiples funciones del encabezado es el de informar del tamaño total del cuerpo del mensaje en caso de que exista. Protocolos como HTTP implementan su propio separador de Mensajes. Ejemplo:

HTTP/1.1 POST /

Content-Length:16

txtNombre=Johan

El ejemplo anterior es un mensaje HTTP, se compone de un encabezado y un cuerpo. El encabezado se compone de un conjunto de Líneas separadas por un tabulado LFCR?? Que se separa del cuerpo del mensaje por una línea en blanco. Si el encabezado contiene una línea Content-Length entonces después de la línea en blanco se recibirá como cuerpo del mensaje el número total de bytes que se especifico en la línea Content-Length, si no se especifica Content-Length, entonces el mensaje se compone solo del encabezado y los siguientes bytes recibidos después de la línea en blanco son tomados como el Encabezado de otro Mensaje.

Para el ejemplo del Mensaje HTTP que se mostro anteriormente corresponde a el siguiente conjunto de bytes:

72, 84, 84, 80, 47, 49, 46, 49, 32, 80, 79, 83, 84, 32, 47, 10,13,67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 49, 54,10,13,10,13,116, 120, 116, 78, 111, 109, 98, 114, 101, 61, 74, 111, 104, 97, 110

Debido a que el encabezado del Mensaje HTTP es siempre ASCII cada byte del encabezado corresponde a un carácter ASCII, la combinación de byte 10(LF, Representado en Espace Unicode de C# como ‘\n’) y 13(CR, Representado en Escape Unicode de C# como ‘\r’) indican que finaliza una Linea del Encabezado HTTP. El dato binario anterior compone un mensaje HTTP completo pero ese dato binario puede recibirse en multiples flujos de datos TCP de cualquier tamaño, Es decir, que podríamos recibir:

  1. 72, 84, 84, 80, 47, 49, 46, 49, 32, 80, 79, 83, 84, 32, 47, 10

  2. 13,67, 111, 110, 116, 101, 110, 116, 45, 76

  3. 101, 110, 103, 116, 104, 58, 49, 54,10,13,10,13,116, 120, 116

  4. 78, 111, 109, 98, 114, 101

  5. 61, 74, 111, 104, 97, 110

Cuando se está percibiendo datos TCP y haciendo un parsing para Formatear Mensajes, se tiene que saber que bytes corresponden a el encabezado del mensaje actual, el contenido del mensaje actual o el encabezado de los siguientes mensajes que se recibirán. Las operaciones a realizar son las siguientes:

  1. Leer todas las líneas del encabezado hasta encontrar una línea en blanco, que equivale a encontrar la secuencia de bytes 10,13,10,13.

  2. Si el encabezado contiene una sentencia Content-Length y su valor es mayor a 0, entonces después del encabezado se tomaran cuantos bytes se reciban como contenido del Mensaje hasta agotar la cantidad especificada. Ejemplo: Si se recibe en el encabezado la línea ‘Content-Length:3563’, entonces se tomaran los 3563 bytes que se reciban en uno o más flujos de datos después de encontrar la secuencia 10,13,10,13.

Ejemplo:

Ultima Línea del Encabezado

Fin de Línea en Blanco

56

34

673

10

13

10

13

43

48

34

Final de Encabezado HTTP

Contenido

En una proxima entrega explicare como se ha implementado este Procolo en C#.

Sunday, November 18, 2007

Separador de Mensajes TCP

Hace tiempo que no escribo y es que he estado trabajando en Demasiadas, Demasiadas cosas interesantes, una de ellas es la reconstruccion de mi Servidor HTTP. La otra tarea no tan trivial es un Protocolo de Mensajeria Interna en LAN y con routing a varios servidores. En fin, el punto es que Ambos requieren que sobre TCP se transmitan diferentes tipos de mensajes. Porque no usar .NET Remoting? Muy pesado para tantas conexiones y necesito hacer clientes en diferentes plataformas basados en un sola definicion de protocolo y no tengo tanta experiencia haciendo SinkProviders de Remoting asi que he decidido hacer un separador de Mensajes TCP. Porque TCP necesita un separador de mensajes? TCP(combinado con IP) es un protocolo de transmision de flujos de datos, no de mensajes. Cual es la diferencia? En un protocolo de Flujo de Datos(Data Stream) se envian los datos en el mismo orden pero no se tiene seguridad de que lleguen de la misma forma y lo voy a explicar asi. Un punto de Red llamado A envia datos a un punto de red llamado B: Punto de Red 'A' Envia los siguientes flujos(cada linea representa un flujo de datos):
  1. 23,34,11,73
  2. 34,67,83,96
El punto de Red 'B'(quien recibe los mensajes) podria recibir los mismos datos en la misma o diferente cantidad de flujos:
  1. 23
  2. 34,11
  3. 73,34,67
  4. 83,96
Como veran los datos llegan en el mismo orden pero no de la misma forma debido a que TCP garantiza que el flujo llegue al destino en el orden original pero no de la misma forma y esto se puede observar en el ejemplo donde 'A' envia 2 flujos pero 'B' recibe 4, sin embargo los bytes llegan de la misma forma. Tambien se puede demostrar esto asi: 'A' envia los siguientes textos representados en flujos(cada linea representa un flujo):
  1. Este es el contenido de el Archivo 1
  2. pero el Archivo 1 tambien tiene otra linea que es esta.
  3. (B, Aqui comienza el Archivo2)
  4. Esta es la linea del Archivo 2
'B' recibe:
  1. Este es el contenido de el
  2. Archivo 1pero el Archivo 1
  3. tambien tiene otra linea que
  4. esta
  5. (B
  6. , Aqui comienza el Archivo2)
  7. Esta es la linea
  8. del Archivo 2
Como podran observar no es posible contar con TCP para manejar conceptos de 'formas de datos', solo podemos contar con TCP para conceptos de 'transmision de datos'. En un protocolo de Red basado en mensajes se Garantiza que los Datos lleguen en el mismo Orden en la Forma original(esto se conoce como 'Mensaje'): Ejemplo: El Punto de Red 'A' envia 2 mensajes:
  1. {23,34,11,73}
  2. {34,67,83,96}
El punto de Red 'B' recibe 2 mensajes:
  1. {23,34,11,73}
  2. {34,67,83,96}
Nota: las llaves indican agrupacion de bytes, es decir, un mensaje completo. Con un protocolo basado en Mensajes se puede tener la seguridad de que los mensajes enviados llegaran de la misma forma con la que fueron enviados. Hay una implementacion de Ordenamiento y Forma de Mensajes de Red llamado SCTP pero es implementado por el Sistema Operativo, no por la aplicacion. Porque no usar SCTP? SCTP es soportado en pocas plataforma(Windows no es una de ellas) sobre IPv6 y mi Protocolo de Mensajeria LAN tiene que funcionar en IPv4 sobre Linux y Windows, ademas debo reutilizarlo para HTTP el cual trabaja sobre IPv4 y IPv6. No tengo mas opciones que desarrollar uno, publicare el codigo fuente pronto en Google Code. En una nueva entrega explicare como funciona HTTP y como estoy desarrollando el separador de mensajes en C# y Mono. Saludos.

Wednesday, October 17, 2007

monodis: Desensamblar aplicacion o libreria de Mono

Entre las herramientas de Mono podemos encontrar la utilidad "monodis"(analoga a la herramienta de Microsoft .NET Framework 'ildasm') que nos funcionara para desensamblar el codigo IL compilado en un ensamblado, ya sea .dll o .exe. ¿Que finalidad tiene ver el codigo IL generado por el compilador? Pues es vital para los desarrolladores de compiladores, util para robar codigo:O o interesante para los curiosos;) Vamos a probarlo! ¿Que vamos a hacer? Crear un archivo de codigo fuente sencillo(main.cs), compilarlo con el compilador de mono 1.1(mcs) y finalmente desensamblarlo con la utilidad monodis. Abrimos una Terminal de Linux o una Consola y ejecutemos los siguientes pasos: Creamos archivo de ejemplo: echo "using System; class MainC{ static void Main(){ Console.WriteLine(\"Saludos\"); } }" > main.cs Compilamos: mcs -out:main.exe main.cs Ejecutamos para probar el compilado: mono main.exe Desensamblamos: monodis --output=main.exe.il main.exe Eso nos ha generado nuestro archivo de codigo fuente IL y ahora vamos a imprimirlo completo en la consola: cat main.exe.il Estos pasos permiten guardar el codigo IL en un archivo pero no es necesario guardar el codigo en un archivo para inspeccionar el desensamblado, con simplemente ejecutar "$monodis nombre-enamblado" ya nos imprimira el codigo IL. Ejemplo: monodis main.exe El resultado tanto del comando anterior como del archivo main.exe.il deberia ser algo parecido al siguiente archivo descargable: main.exe.il Listo! Estoy preparando una manual practico para entender IL, en los proximos dias lo estare publicando. Saludos!

Wednesday, September 12, 2007

Medir Periodos de Tiempos en C#

En .NET 2.0 y disponible tambien en Mono tenemos la clase System.Diagnostics.Stopwatch que nos permite medir con milisegundos el tiempo transcurrido en un periodo. Ejemplo: System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); System.Threading.Thread.Sleep(100); watch.Stop(); System.Console.WriteLine("Transcurrido: {0}", watch.ElapsedMilliseconds); Realmente util no? Hace tiempo habia implementado uno para medir los tiempos de ejecucion pero este esta sencillo y practico.

Saturday, July 21, 2007

How to MD5 in .NET & Mono

Simple code: using System.Security.Cryptography; //... private readonly static MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); public static string CreatePasswordMD5(string password) { MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); byte[] bs = System.Text.Encoding.UTF8.GetBytes(password); bs = md5.ComputeHash(bs); System.Text.StringBuilder s = new System.Text.StringBuilder(); foreach (byte b in bs) { s.Append(b.ToString("x2").ToLower()); } return s.ToString(); } // Usage: Console.WriteLine(CreatePasswordMD5("p@ssw0rk!"));

Wednesday, May 23, 2007

WindowsClient.net

Ya se ha lanzado http://windowsclient.net, sitio web que facilita muchos recursos para el desarrollo de aplicaciones WindowsForms and WindowsPresentationFoundation, lo menciono porque ya Mono 1.2.4 soporta la mayoria de los nuevos controles de WindowsForms2.0, de hecho, aunque yo no lo he probado, en el blog de miguel de icaza se puede ver como Paint.NET 3 corre sobre Mono 1.2.4. En resumen, en el site encontraran muchos controles. Lo bueno es que estan categorizados los de WindowsForms y los de WPF asi que no hay porque confundirse, esperemos por Mono Olive y su WPF en 2 o 3 años mas.

Tuesday, May 22, 2007

Microsoft .NET Entity Framework

Microsoft introducira pronto un lenguage de Consulta sobre LINQ llamado por el momento eSQL(Entity Structured Query Language) y me parece excelente, era lo que hacia falta para combinar los tipos anonimos de C# 3.5 con acceso a datos. Puedes hacer algo como esto: SELECT p.ProductName, p.UnitPrice FROM NorthwindContainer.Products as p ORDER BY p.ProductName Desc Segun el ejemplo me estoy ahorrando un INNER JOIN y solo estoy tratando entidades de datos. Muy bueno, solo espero que normalize los resultados y traduzca el eSQL a todo tipo de bases de datos. No mas GetString(int ordinal) aunque con lambda expressions era mas facil(("AccountName")=>reader.Read)). El articulo TSS.NET explica todo con detalle y se los dejo a la mano. De todas formas no se emocionen porque saldra despues de orcas, a mediados 2008 o 2009 con el tipico SP de Visual Studio que sale en el primer año jejejeje. Ahora, muchas facilidades para consulta de datos directos verdad? que paso con aquello de crear todo en procedimientos almacenados? No, no hay SQL Injection posible en LINQ, pero estaria optimizado? No.. o sera que el proveedor lee mi codigo IL para precompilar SQL? No lo creo.

Monday, May 21, 2007

C# Mono HTTP Server

Hace tiempo habia creado un servidor Http en C# y Mono siguiendo la arquitectura de Isolated Applications de Asp.net, lo he desempolvado para poder utilizarlo en para lo que finalmente lo habia necesitado, mi framework de aplicaciones. Lo hice hace como 1 año atras: Soporta:
  • Application Tree
  • Isolated Applications Activation
  • Application State(Offiline,Online)
  • Cookies
  • MimeTypes
  • KeepAlive
  • Buffering
  • Encodings
  • Http Redirection
  • Http Resources Tree
  • Http Resources Activation
  • Exception Handling(Local,Remote information)
  • Port Publication.
  • SSL(con algunos bugs fantasmas)
En perfomance esta bastante aceptable, realice unas pruebas de carga con Firefox y unos script con autorefresh y pude calcular calcule 20 clientes(20 pestañas de firefox) respondiendo a 150ms cada solicitud de 672 KB fijos, 34MB de memoria de consumo de proceso de servidor y 73%(compartido con firefox) de mi procesador Pentium4 2.8Ghz. Puede que no sea el benchmark mas perfecto pero algo es algo, despues de darme cuenta de que podia hacer mi framework incluyendo sus 5 servidores completamente en C# desisti y ataque otro problema para el momento. Ahora es tiempo de reescribirlo para implementar todo esto:
  • SessionState
  • ApplicationState
  • Resources Pooling
  • Authorization
  • Authentication
  • Server/Client Buffering
  • Mutexes
  • Caching
  • Configuration File Directory Dependendy(Depende de AppDomain.SetConfigurationBytes que aun no esta implementado en Mono)
  • Virtual Relative/Absolute Paths checking.
Tambien hay que rediseñar todo esto:
  • Server/Application Buffering: Eliminar el hashtable de solicitudes y utilizar Pipelined Streams(un 10% de adicional de perfomance)
  • Reemplazar el parsing del HTTP Header un Regex.(un 2% adicional de perfomance)
  • Process Isolation and Application Pooling
  • Statistics
  • Host Naming
  • SSL: Implementar PKI.
En fin es un arduo trabajo, hasta el momento la api esta sencilla: BinDeal.Foundation.Net.Http.Server.HttpServer server = new BinDeal.Foundation.Net.Http.Server.HttpServer("BinDeal-WebServer"); server.Publications.Register( new HttpServerPublication( new HttpStandardEndPoint(8089), null, true, System.Net.IPAddress.Any, int.MaxValue)); HttpApplicationSetup setup = new HttpApplicationSetup(); setup.ApplicationName = "DefaultApp"; ApplicationDebugParams prms = new ApplicationDebugParams(); prms.Enabled = true; setup.Debug =prms; setup.EntryPointTypeName = typeof(FileBrowserAppEntry).AssemblyQualifiedName; HttpWebApplication webApp = new HttpWebApplication(setup); server.Applications.SetRoot(webApp.IdResource); webApp.TakeOnline(); server.Start(); Aqui les coloco algunos screenshots de una pequeña aplicacion web para explorar mis archivos de la PC.

Sunday, April 29, 2007

Embedding Mono

Embedding mono es el proceso en el cual se incrusta el Mono Runtime en otro proceso generalmente creado en C o C++. Siguiendo los pasos de la guia oficial de mono he creado este pequeño ejemplo para hacer ejecutar una aplicacion Ejecutable de Mono desde una aplicacion hecha en C. El demo incluye:
  • main.c : Archivo con el embedding para el Runtime de Mono
  • main.cs : Archivo de C# para generar ejecutable.
  • Makefile : Archivo para compilar y ejecutar todo.
[Descargar mono_embedding_exe.tar.gz] Basicamente los pasos son los siguientes:
  1. mono_jit_init y recibir un puntero al dominio de aplicacion.
  2. mono_domain_assembly_open y recibir un puntero al ensamblado.
  3. mono_jit_exec y pasarle el ensamblado y el dominio
  4. mono_jit_cleanup para limpiar la instancia de CLR.
Es todo. Me he tomado el trabajo porque actualmente en mi poco tiempo libre estoy intentando hacer wrappers del x-chat. La verdad lo que necesito es ejecutar una clase en una libreria y aun no lo consigo:P (Continua)

Sunday, April 22, 2007

Proyecto Personal Enabled!

Sorprendentemente alguien me ha comprado mi idea (por asi decirlo) y ya hemos empezado a desarrollarla. Es un framework para desarrollo de aplicaciones distribuidas para linux construido 100% en C#/Mono incluyendo un servidor de datos, un servidor de procesos de negocios y un servidor de presentacion que no es ASP.NET. El tiempo de desarrollo aproximado esta entre 5 a 7 meses a partir del miercoles 23 de Abril y despues de ese periodo desconocemos como realizaremos una estrategia comercial aunque se proponen distribucion propietaria de muy bajo costo(diagmos unos 100$), Freeware o hasta LGPL. Soportara inicialmente Linux+Postgres y de acuerdo a la demanada se soportaran otros sistemas operativos y bases de datos. Debido a que aun no hemos comprado el dominio en internet no puedo dar el nombre oficial pero esta relacionado a un elemento de la tabla periodica(eso creo...). Probablemente mi blog sea la fuente principal de noticias del asunto hasta que todo salga a la luz publica con un fin comercial.

Monday, February 19, 2007

Example: Gnome.Sound class

Codigo fuente: TestGnomeSound.cs(Download Source) Namespaces: Gnome Clases: Gnome.Sound Ensamblados: gnome-sharp.dll Portabilidad: Linux, Gnome - Desarrollo de Aplicaciones Linux usando Novell Mono y Gnome Desktop. Introducción: Este ejemplo introduce al uso de la clase Gnome.Sound de Mono Linux usando el entorno de escritorio Gnome para reproducir sonidos WAV

Example: Gnome.PasswordDialog Class

Codigo fuente: GnomePasswordDialogSample.cs(Download Source) Namespaces: Gnome Clases: Gnome.PasswordDialog Ensamblados: gnome-sharp.dll Portabilidad: Linux, Gnome - Desarrollo de Aplicaciones Linux usando Novell Mono y Gnome Desktop. Introducción: Este ejemplo introduce al uso de la clase Gnome.PasswordDialog de Mono Linux usando el entorno de escritorio Gnome para mostrar y obtener los datos del cuadro de dialogo de credenciales de Gnome como se muestra a continuación:

Friday, January 19, 2007

Enumerando la Información de las Unidades de Almacenamiento utilizando Visual Studio 2005 y C# 2.0

Materiales: DrivesInfo-Example.cs DrivesInfo-Example.zip Namespaces: System;System.IO; Clases: System.IO.DriveInfo Ensamblados: Mscorlib.dll(Referencia no necesaria) Portabilidad para Mono: Ninguna. Mono 1.2.1 Aun no ha implementado la clase DriveInfo. - Tema para examen oficial Application Development Foundation(70-536). - Certificacion MCTS. Introducción: A menudo uno necesita crear aplicaciones que guarden archivos(XML,TXT,DAT) en el Sistema de Archivos de Windows y por supuesto necesitara saber que unidades y que espacio libre le quedara a cada unidad del usuario. En Microsoft .NET Framework 2.0 se complemento el namespace System.IO con clases y metodos que proporcionan la informacion que necesitamos: Ejemplo: 1) Obtener las instancias de DriveInfo con la informacion de cada Unidad: DriveInfo[] drives = DriveInfo.GetDrives(); 2) Iterar el Array para poder presentar la información de cada Unidad: foreach (DriveInfo info in drives) {...} (Los puntos suspensivos en el codigo dado y en los siguientes indican porciones de codigo no relevante para el paso que se esta explicando) 3) Comprobar el estado de la unidad para solicitar la informacion. Esto se hace mediante la propiedad IsReady, de otra menera si se intenta obtener la información y la unidad no esta lista se levantara una excepción de tipo System.IO.IOException. Un caso tipico de esta situación es la unidad de Diskette(que casi nunca para mi caso tiene un disco): if (info.IsReady) {...} Seguidamente podra mostrar la informacion completa de la unidad. Si se compila y ejecuta la aplicación de ejemplo obtendra un resultado similar: A:\ no tiene disco C:\:Bill gates 39070 MB 39 GB, NTFS D:\ no tiene disco E:\:WD160GB 140665 MB 140 GB, NTFS F:\:SG80GB_EMULE 78140 MB 78 GB, NTFS G:\ no tiene disco H:\:VSSD1 105 MB 0 GB, UDF