Compartir sesiones con MySql en diferentes servidores

Muchos sitios necesitan correr desde varios servidores, por ejemplo para aprovechar la localidad
de los usuarios con respecto al servidor, para balancear la carga, para compartir usuarios registrados o simplemente como resguardo
por si alguno de los sitios falla. Uno de los aspectos a contemplar para este menester es el
manejo de sesiones, aqui explicamos como mantener sesiones entre multiples servidores.




Descripcion del problema


Supongamos que tenemos 2 servidores que corren el mismo sitio por ejemplo mexico.foo.org y espana.foo.org,
los sitios pueden ser exactamente iguales o bien tener algunas diferencias entre si, lo que es claro es que
los usuarios de foo.org pueden comenzar por cualquiera de los sitios y moverse de un sitio a otro si les
parece conveniente


Sesiones


El uso de sesiones permite mantener presistencia entre las distintas paginas de un site en forma limpia
y eficiente, PHP4 permite manejar sesiones en forma sumamente sencilla, por ejemplo:













session_start();
$data="hola";
session_register("data");




Todas las paginas que usen sesiones deben empezar con session_start() o al menos hacer el session_start() antes de generar cualquier tipo de salida al browser. Una vez inicializada la sesion se utiliza session_register para guardar una variable en la sesion, notar que a session_register se le pasa elnombre de la variable y no la variable misma.
Una vez registrada la variable podemos tener otra pagina php distinta con:













session_start();
echo "$data";




Y la variable $data tomara el valor "hola" ya que habia sido guardada en la sesion con dicho nombre, se puede tambien
eliminar variables de la sesion y algunas otras cosas mas, pueden encontrar el manual en español sobre el uso de sesiones en esta direccion


Bien, podemos suponer ahora que sabemos usar sesiones, las sesiones son muy utiles para llevar datos pertenecientes
al usuario, como por ejemplo su userid u otros datos importantes, si tenemos dos servidores para el mismo sitio es logico
que la sesion se mantenga cuando el usuario pasa de un sitio a otro, pero esto no ocurre automaticamente


El problema


Internamente y sin modificaciones PHP4 guarda los datos de las sesiones en /tmp, periodicamente el mecanismo de "garbage collection" elimina las sesiones vencidas, la duracion maxima de una sesion sin actividad puede configurarse en php.ini (usualmente en /usr/local/lib). Como es evidente al cambiar de un servidor a otro el segundo no tiene acceso al directorio /tmp del primero por lo que la sesion se pierde, el session_start del nuevo servidor mas que abrir la sesion anterior debe crear una nueva y perdemos los datos que veniamos arrastrando en la sesion


Una primera alternativa que funciona es usar NFS para que los dos servidores puedan acceder a /tmp en un mismo lugar, sin embargo, esto no siempre es posible y muchas veces no queremos usar NFS unicamente por esta razon.


La solucion al problema


La solucion mas practica al problema de la persistencia de la sesion entre multiples servidores reside en usar una base de datos, por ejemplo MySQL, para almacenar los datos de la sesion. De esta forma ambos servidores pueden acceder a la misma base de datos (en un solo servidor) para consultar los datos de la sesion. Tantos servidores como deseemos pueden compartir la sesion siempre y cuando puedan acceder al mismo servidor MySQL.


Para que los datos de la sesion se guarden en MySQL es necesario modificar la forma en que PHP maneja sesiones


Cambiando los Session-Handlers


PHP4 dispone de un mecanismo que permite cambiar la forma en la cual se almacenan las sesiones por cualquier metodo que el usuario desee, para ello se usa la funcion session_set_save_handler. La funcion recibe 6 parametros que son los nombres a 6 funciones que se describen a continuacion:




  • Primera funcion:Abrir la sesion

  • Segunda funcion:Cerrar la sesion

  • Tercera funcion:Leer los datos de la sesion

  • Cuerta funcion:Escribir los datos de la sesion

  • Quinta funcion:Destruir una sesion

  • Sexta funcion:Eliminar sesiones vencidas


Por ejemplo:













session_set_save_handler ( 
'mysql_session_open',
'mysql_session_close',
'mysql_session_read',
'mysql_session_write',
'mysql_session_destroy',
'mysql_session_gc' );




En el ejemplo seteamos los nombres de las 6 funciones que seran usadas para manejar sesiones, veamos ahora que
prototipo debe tener y que hace cada funcion










































FuncionPrototipoDescripcion
mysql_session_openmysql_session_open($sess_path, $session_name);Esta funcion es llamada para inicializar la sesion, recibe el path en donde guardar las sesiones si se usan archivos y el bombre de la sesion, en MySQL ninguno de los parametros nos interesa
mysql_session_closemysql_session_close()Esta funcion se llama cuando la pagina termina y el handler necesita dejar cerrado el archivo o lo que sea que haya usado para mantener la sesion, no elimina la sesion solo deja todo listo para volver a abrirla con open
mysql_session_readmysql_session_read($key)Esta funcion se usa para leer los datos asociados a una sesion,las sesiones se identifican por una clave que se recibe como parametro, no es necesario preouparse por los datos que se recuperan ya que esto lo maneja php4 internamente, si el usuario registra 4 variables los handlers solo guardan y recuperan un par clave-valor, la forma en que las 4 variables se serializan y desserializan esta a cargo del PHP
mysql_session_writemysql_session_write($key,$val)Esta funcion se usa para almacenar el contenido de la sesion indicada por $key, $val tiene todas las variables de la sesion serializadas y listas para ser almacenadas.Est funcion se suele llamar al final de cada script antes de hacer el close.
mysql_session_destroymysql_session_destroy($key)Es invocada para eliminar los datos de una sesion.
mysql_session_gcmysql_session_gc($maxlifetime)Esta funcion debe eliminar todas las sesiones que tengan mas de $maxlifetime segundos de vida.


Preparando la base para guardar sesiones


Una vez que hemos analizado como funcionan los handlers es bueno analizar como vamos a guaradar la informacion en MySQL, si entendimos bien el mecanismo solo necesitamos guardar algo de tipo clave-valor por cada sesion y ademas un timestamp que permita saber hace cuanto tiempo que no se usa la sesion. Podemos crear una tabla de la forma:













DROP TABLE IF EXISTS PHPSessions;
CREATE TABLE PHPSessions (
SessionID CHAR(32) NOT NULL PRIMARY KEY,
LastActive INTEGER NOT NULL,
Data TEXT
);



SessionID es la clave de la sesion, LastActive la ultima fecha de uso de la sesion y Data los datos de la sesion, notemos que al estar definida como PRIMARY KEY la columna SessionID esta indexada lo cual agiliza mucho el manejo de sesiones cuando hay miles de usuarios en el sistema.


Handlers para Mysql


Analicemos ahora que debe hacer cada funcion para almacenar las sesiones en Mysql



































FuncionDescripcion
mysql_session_open($path,$name);En esta funcion tenemos que abrir la conexion a la base, usar mysql_pconnect con una conexion persistente es muy recomendable, ademas seleccionamos la base con mysql_select_db. Los dos parametros que recibe la funcion se ignoran.
mysql_session_close();Aqui no hace falta hacer nada ya que no es necesario cerrar la conexion a la base
mysql_session_read($key);Esto es simplemente un select a la base y devolvemos la columna data para la clave recibida. Ademas actualizar el timestamp del registro.
mysql_session_write($key,$data);Aquie hay que hacer un update si la sesion ya existe o bien un insert en caso contrario. Ademas actualizamos el timestamp del registro.
mysql_session_destroy($key);Un simple delete de la base
mysql_session_gc($maxlifetime);Borramos de la tabla todos los registros para los cuales la diferencia entre el ultimo tiempo de acceso y el actual sea mayor al parametro recibido


El codigo


Una vez analizado que es lo que hay que hacer solo resta programarlo, a continuacion presentamos el codigo y que pueden obtener tambien desde este link













<? 
// This code is released under the same license as PHP

$SessionTableName = "PHPSessions";
assert(!empty($SessionTableName));

function mysql_session_open ($save_path, $session_name) {
mysql_pconnect("HOST","USER","PASS");
mysql_select_db("BASE");
return true;
}

function mysql_session_close() {
return true;
}

function mysql_session_read ($SessionID) {
global $SessionTableName;

$SessionID = addslashes($SessionID);

$session_data = mysql_query("SELECT Data FROM $SessionTableName
WHERE SessionID = '$SessionID'") or die(db_error_message());
if (mysql_numrows($session_data) == 1) {
return mysql_result($session_data, 0);
} else {
return false;
}
}

function mysql_session_write ($SessionID, $val) {
global $SessionTableName;

$SessionID = addslashes($SessionID);
$val = addslashes($val);

$SessionExists = mysql_result(mysql_query("SELECT COUNT(*) FROM $SessionTableName
WHERE SessionID = '$SessionID'"), 0);

if ($SessionExists == 0) {
$retval = mysql_query("INSERT INTO $SessionTableName
(SessionID, LastActive, Data)
VALUES ('$SessionID', UNIX_TIMESTAMP(NOW()), '$val')")
or die(db_error_message());
} else {
$retval = mysql_query("UPDATE $SessionTableName SET
Data = '$val', LastActive = UNIX_TIMESTAMP(NOW())
WHERE SessionID = '$SessionID'") or die(db_error_message());
if (mysql_affected_rows() == 0) {
error_log("unable to update session data for session $SessionID");
}
}

return $retval;
}

function mysql_session_destroy ($SessionID) {
global $SessionTableName;

$SessionID = addslashes($SessionID);

$retval = mysql_query("DELETE FROM $SessionTableName
WHERE SessionID = '$SessionID'") or die(db_error_message());
return $retval;
}

function mysql_session_gc ($maxlifetime = 300) {
global $SessionTableName;
$CutoffTime = time() - $maxlifetime;
$retval = mysql_query("DELETE FROM $SessionTableName
WHERE LastActive < $CutoffTime") or die(db_error_message());
return $retval;
}

session_set_save_handler (
'mysql_session_open',
'mysql_session_close',
'mysql_session_read',
'mysql_session_write',
'mysql_session_destroy',
'mysql_session_gc' );
?>




Como usar el los nuevos handlers


Para usar los nuevos handlers tenemos que, en primer lugar crear la tabla PHPSessions con el codigo provisto para alguna base mysql, si se quiere se puede crear una nueva base para las sesiones, una vez creada la tabla modificar el script con los handlers indicando HOST,USER,PASS y BASE en la funcion mysql_session_open, luego solamente resta poner el script en el servidor y hacer un include del mismo "antes" del session_start, y eso es todo, pueden probarlo y ver como los datos se almacenan en la tabla y se mantiene la persistencia de la sesion. Para usarlo en otro server el proceso es el mismo, no olviden poner correctamente el HOST, USER,PASS en la funcion de conexion para que los dos servidores se conecten a la misma base MySQL.


Conclusiones


Las tecnica que hemos descripto permite compartir sesiones facilmente entre servidores y ademas ha demostrado ser
mucho mas limpia y eficiente incluso en instalaciones con un unico servidor, esta es una de las cosas a tener en cuenta
cuando nos lancemos a construir multiples sitios o sitios que quieran compartir usuarios en forma limpia y efectiva.

Silverlight: Universal GUI toolkit

The most important piece of news from last week's PDC was Microsoft's decision to turn Silverlight into the universal platform for building cross platform applications.

The upcoming version of Silverlight will no longer be a Web-only technology. It will now be possible to build full desktop applications with Silverlight.

Desktop Silverlight applications differ from the standard Silverlight in a few ways:

  • Full access to the host file system, like any other .NET application would have.

  • None of the socket connectivity limitations that are present on the sandboxed versioned of Silverlight. Full network access (we should build a MonoTorrent UI for it!)

  • Built-in Notifications API to show up bubbles to the user when they need to interact with the application.


Although Moonlight has supported this mode of operation since day one, turning this into a standard way to develop applications was going to take a long time. We would have needed to port Moonlight to Windows and OSX and then we would have to bootstrap the ecosystem of "Silverlight+" applications.

But having Microsoft stand behind this new model will open the gates to a whole new class of desktop applications for the desktop. The ones that I was dreaming about just two weeks ago.

This was a big surprise for everyone. For years folks have been asking Microsoft to give Silverlight this capability to build desktop apps and to compete with Air and it is now finally here. This is a case of doing the right thing for users and developers.

Desktop Tools in Silverlight?


Now that this technology is available, perhaps it is a good time to start a movement to create a suite of Silverlight-based desktop applications.

The benefits to me are many:

  • .NET applications that actually look good. In the past your choices were basically of Gtk# or Winforms, neither one really designed for this graphic-designer driven world.

  • We can join forces with Windows/MacOS developers to create the next generation of desktop applications.

  • Developers can tap into the large ecosystem of third-party controls that exists for Silverlight.


For the Moonlight team, this means that there is a lot of work ahead of us to bring every Silverlight 3 and 4 feature. I think I speak for the whole Mono team when I say that this is exciting, fascinating, challenging and feels like we just drank a huge energy boost drink.

If you want to help, come join us in the #moonlight or #mono channels on the IRC server at irc.gnome.org.

Silverlight 4


There are many other great features in Silverlight 4, but none as important as Silverlight becoming a universal runtime for the CLR. This is a revolution.

If you are curious about all the new tactical features of the revolution, check Tim's Complete Guide to the new Silverlight Features.

If you have the time, watch Scott's keynote's presentation where he introduced the new features (he starts at 1:02). I loved the use of HTML as a Silverlight brush (paint with HTML and even Flash). If you have time, these are some great sessions on Silverlight:

Invocar funciones PHP desde Flex con AMFPHP

Adobe Flex es un framework de desarrollo que nos permite crear rápida y facilmente aplicaciones RIA (Aplicaciones de Internet Enriquecidas), basado en la plataforma Flashcombinando el lenguaje de marcas MXML ActionScript. También, gracias a su entorno de desarrollo se simplifica el desarrollo de aplicaciones AIR.


En esta oportunidad quiero explicar cómo hacer uso de Flex para invocar funciones hechas enPHP (no entraré en detalles, pues no conozco a fondo ActionScript). Una forma de hacerlo es mediante AMFPHP. Pero ¿qué es AMFPHP? Es un RPC (Llamada a Procedimientos Remotos) que nos permite comunicar datos de aplicaciones-funciones entre el cliente (JavaScript, Flash, Flex, etc) y servidor (PHP, ASP, JSP, etc). En este caso AMFPHP realiza la comunicación de procesos remotos entre Flash (y por extensión aplicaciones RIA en Flex y AIR) y PHP.


Vamos por paso para la implementación de un proyecto en Flex que llame a funciones en PHP.


1. Descargar y extrae la carpeta amfphp que contiene la siguiente estructura (y para no perderse en el tutorial, colocala en la raíz de tu sitio web de tal forma que quede así:http://localhost/amfphp)



+ ampphp
 
+services
 
+core
 
+browser
 
-gateway.php
 
-globals.php
 
-.htaccess
 
-json.php
 
-xmlrpc.php
 
-phpinfo.php

2. Verificar el funcionamiento del amfphp. Para ello abres tu navegador y escribeshttp://localhost/amfphp/browser. Aparecera una ventana de configuración donde se muestra la ubicación del archivo gateway que actuará como puerta de enlace. En esta ventana solo dale clic en Save.


Podrás apreciar un especie de explorador. En la vista árbol a tu izquierda se mostrarán todas las clases en PHP que podemos usar. Para que una clase aparezca allí debes guardarla en el directorio services.


3. Vamos crear una clase en PHP. Vamos a lista una relación de clientes de una base de datos MySQL. La estructura de la tabla es la siguiente (ingresa un par de registros luego):



CREATE TABLE IF NOT EXISTS `cliente` (
 
`id` tinyint(7) NOT NULL auto_increment,
 
`nombres` varchar(50) NOT NULL,
 
`ciudad` varchar(50) NOT NULL,
 
`sexo` char(1) NOT NULL,
 
`telefono` varchar(10) NOT NULL,
 
`fecha_nacimiento` datetime NOT NULL,
  KEY
`id` (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

En archivo PHP debe tener el mismo nombre que la clase, en este caso se llama sample.php:



<?php
class sample{
   
function getUsers () {
        $mysql
= mysql_connect(localhost, "root", "");

        mysql_select_db
( "empresa" );

                $Query
= "SELECT * from cliente";
                $Result
= mysql_query( $Query );
               
while ($row = mysql_fetch_object($Result)) {
                        $return
[] = $row;
               
}
               
return( $return );
       
}
}
?>

Volvamos a http://localhost/amfphp/browser y podemos apreciar en la lista de servicios, a la mano izquierda, nuestra clase llamada sample. Si la seleccionamos se muestran sus métodos, en este caso getUsers, y pulsamos el botón call se mostrará el resultado en la parte inferior.


amfphp browser


4. Abrimos Flex (en mi caso Flex Builder 3) y creamos un nuevo proyecto Flex de nombresample.


new project


new project


Configuramos la ruta en nuestro servidor local:


new project


new project


El archivo autogenerado sample.mxml lo dejamos allí por un momento. Ahora vamos agregar un archivo de ActionScript a nuestro proyecto, para ello le damos clic derecho en la carpeta srcy seleccionamos New ActionScript File.


new project


new project


El archivo RemotingConnection.as contiene un clase que llama a una conexión remota especificando la url de ésta.



package {
       
import flash.net.NetConnection;
       
import flash.net.ObjectEncoding;

       
public class RemotingConnection extends NetConnection
       
{
               
public function RemotingConnection( sURL:String )
               
{
                        objectEncoding
= ObjectEncoding.AMF0;
                       
if (sURL) connect( sURL );
               
}

               
public function AppendToGatewayUrl( s : String ) : void
               
{
                       
//
               
}
       
}
}

Ahora el archivo autogenerado sample.mxml, lo reemplazamos por el siguiente contenido:



<?xml version="1.0" encoding="utf-8"?>

       
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns="*" creationComplete="initApplication()">

       
<mx:DataGrid dataProvider="{dataProvider}">
               
<mx:columns>
                               
<mx:DataGridColumn headerText="ID" dataField="id"/>
                               
<mx:DataGridColumn headerText="Nombres" dataField="nombres"/>
                               
<mx:DataGridColumn headerText="Ciudad" dataField="ciudad"/>
                               
<mx:DataGridColumn headerText="Telefono" dataField="telefono"/>
                               
<mx:DataGridColumn headerText="Sexo" dataField="sexo"/>
                               
<mx:DataGridColumn headerText="Fecha Nacimiento" dataField="fecha_nacimiento"/>
                       
</mx:columns>
       
</mx:DataGrid>

       
<mx:Script>
                <![CDATA[
                        [Bindable]
                        public var dataProvider:Array;
                        public var gateway : RemotingConnection;

                        public function initApplication()
                        {
                                gateway = new RemotingConnection( "http://localhost/amfphp/gateway.php" );
                                gateway.call( "sample.getUsers", new Responder(onResult, onFault));
                        }

                        public function onResult( result : Array ) : void
                        {
                                dataProvider = result;
                        }

                        public function onFault( fault : String ) : void
                        {
                                trace( fault );
                        }
                ]]>
       
</mx:Script>

</mx:Application>

Hemos creado un DataGrid para mostrar los datos de la consulta al servidor MySQL. Dentro de las etiquetas <mx:Script/> hacemos uso de ActionScript para llamar a la claseRemotingConnection que creamos anteriormente. La función initApplication() se encarga de conectar con la puerta de enlace: gateway.php, y llama al método getUsers() de la clasesample. La respuesta la recibe la función onResult() que pasa los datos a la variabledataProvider y ésta pasa al DataGrid.


6. Ahora simplemente compilamos el proyecto (Ctrl + F11) y podemos apreciar el resultado en el navegador web.


new project


De esta forma podemos crear aplicaciones web complejas que incluyan inserción y actualización de datos. Pero eso no esto, incluso podemos crear aplicaciones de escritorio gracias a AIR con esta funcionalidad, es decir llamadas a procesos remotos. Les dejo los archivos de este tutorial para que lo prueben en su servidor local.


Lo vi en: Flex and PHP Using AMFPHP

Parecidos entre lenguajes de servidores y las mujeres

100 Continue ==== Sigue intentándolo vas por buen camino
101 Switching Protocols ==== Si no te decides...
303 See Other ==== Pruebalo con otra
400 Bad Request ==== Dímelo con flores
401 Unathorized ==== Estoy casada
402 Payment Required === Son 10.000 y la cama
403 Forbidden/Access Required === ZZZZZZZAS! (bofetón)
404 Not Found === He quedado con las amigas
405 Method Not Allowed === No, por detrás no...
406 Method Not Acceptable === ... y en la boca menos
407 Proxy Auth. Required === Lo hablaré con mi madre
408 Request Timeout === ¿Sabes cuánto hace que no me llamas?
409 Conflict === ¿Quien era ESA?
410 Document Removed === Quiero el D-I-V-O-R-C-I-O
411 Lenght Required === ¿A eso llamas 'pedazo polla'?
412 Precondition Failed === ¿Que no has traido condones?
413 Request Entity Too Large === Eso no me va a caber ahí dentro
414 Request URL Too Large === Eso tampoco me va a caber ahí dentro
415 Unsupported Media Type === A cuatro patas no me gusta
500 Internal Server Error === Tengo la regla
501 Not Implemented === Nunca haría *eso*
502 Bad Gateway === ...y por ahí, menos todavía
503 Service Unavailable === Me duele la cabeza
504 Gateway Timeout === ¿Ya está?

Y no hay que olvidar el raro e infrecuente
200 OK === Chica facilona

Dia del codigo de barras

google-codeSi hicieron una búsqueda en Google hoy, quizás habrán notado que algo extraño le pasó al logo. El nuevo “doodle” que aparece hoy, y que debiera ser fácilmente reconocido por todos, celebra los 57 años del código de barras.


El invento, que ha facilitado las compras en el supermercado en el mundo (entre otras cosas), fue patentado el 7 de Octubre de 1952 por los ciudadanos del país del consumismo estadounidenses Norman Joseph Woodland y Bernard Silver.


Silver, quien administraba una cadena de locales de comida, buscó crear un sistema que facilitara la lectura de los datos de los productos de forma automática. Para ello se asoció con el profesor del Instituto Tecnológico Drexel, de donde se había graduado, y crearon el hoy universal código de barras.


La primera versión consistía en una serie de círculos concéntricos, que luego fue reemplazada por las líneas rectas que se utilizan hasta hoy.


Link: Bar code: invention history behind new Google doodle (Telegraph)

C# (C Sharp) Mejor que JAVA???? Opinen

bueno, tratare de ir posteando lo k vaya aprendiendo en este lenguaje

les dejo un poco de teoria

“Muchos dicen que si Java se puede considerar un C++ mejorado en cuestiones de seguridad y portabilidad, C# debe entenderse como un Java mejorado en todos los sentidos: desde la eficiencia hasta la facilidad de integración con aplicaciones tan habituales como Microsoft Office o Corel Draw."

Las frases del inge pollis en facebook!

Bueno por algo se empieza y en esta ocasión les presento mi aplicacion  en Facebook, es algo sencillo. Pero esta muy divertido..



Las frases del inge pollis!

Google festeja hoy sus 11 años Online (¿de vida?)

El 27 de septiembre parece haber sido la fecha elegida por la empresa que hoy mismo cambia su logopara celebrarlo, aunque muchas personas discrepan y consideran que el nacimiento de Google tuvo lugar el día 15 del mismo mes





[caption id="" align="alignnone" width="600" caption="11 años de google"]11 años de google[/caption]

Hoy Google celebra su cumpleaños número 11 y para celebrarlo agregó una letra L extra: Googlle (Goog11e).

El aniversario de Google se celebra durante el mes de septiembre, no tiene una fecha exacta, aunque en2002 y 2005 (y ahora 2009) se escogió el día 27 de septiembre para celebrarlo desde el logo del buscador.

Con once primaveras a sus espaldas y convertidos en la mayor empresa de internet, Google nos regala, semana a semana, todas las novedades para hacer más sencilla nuestra navegación por la red.

Según figura en los archivos, fue fundada el 7 de septiembre de 1998 por Larry Page Sergey Brin(dos estudiantes de doctorado en Ciencias de la Computación de la Universidad de Stanford).

Aunque su principal producto es el buscador, la empresa ofrece también entre otros servicios: un comparador de precios llamado Google Product Search (antes conocido como "Froogle"), un motor de búsqueda para material almacenado en discos locales (Google Desktop Search), y el servicio de correo electrónico llamado Gmail, el cual pone a disposición para sus usuarios más de 7 GB[2] de espacio. 

También es famoso su programa Google Earth, un mapamundi en 3D con imágenes de alta resolución. Recientemente lanzó su versión beta de un servicio de mensajería instantánea basado en Jabber/XMPP llamado Google Talk.

Encontrar el valor de un Window Message

De vez en cuando, si trabajamos con WinForms, nos puede surgir la necesidad de manejar un evento a muy bajo nivel y para hacerlo tenemos que interceptar los famosos Window Messages, o mensajes de ventana. Estos mensajes son el mecanismo que utiliza Windows para comunicarse con una aplicación. Cuando apretamos una tecla y nuestra aplicación responde, parece que es nuestra aplicación la que ‘atrapó’ el teclazo, pero en realidad es el Sistema Operativo (SO) el que lo atrapó (debido a que el SO es quien controla el puerto donde esta conectado el teclado) y este le envía un mensaje a nuestra aplicación para que responda al mismo, normalmente imprimiendo el caracter representado por la tecla presionada. Aunque no lo parezca, el SO es quien tiene control de todo lo que sucede y cuando nuestra aplicación responde a distintos inputs, es en realidad el SO el que le ordena que haga una cosa u otra.


Si tenemos un Form y el SO determina que es necesario que sea redibujado (porque cambio su contenido por ejemplo), entonces se envía un mensaje conocido como WM_PAINT (en .NET veremos que esto dispara el evento Paint), en cambio si presionamos la tecla ‘Q’ en el teclado, entonces el mensaje recibido por nuestra aplicación es WM_KEYDOWN (también tenemos el evento KeyDown en .NET, el cual es lanzado cuando se recibe un mensaje de este tipo). Cabe aclarar que el nombre de los mensajes es solo una ayuda para nosotros los humanos, ya que los mensajes en realidad no son más que un valor entero, y estos nombres son los nombres de las constantes asociadas a los mismos.


Para interceptar estos mensajes lo que se suele hacer comúnmente es sobrescribir el métodoWndProc definido en la clase Control de la siguiente manera:



 1: ...

   2: private const int WM_PAINT = 15;

   3:

   4: protected override void WndProc(ref Message m) {

   5:

   6:     if (m.Msg == WM_PAINT) {

   7:         // Atrapamos el mensaje...

   8:     } else{

   9:         // Ignoramos el mensaje y dejamos que siga su curso

  10:         base.WndProc(ref m);

  11:     }

  12:

  13: }

  14: ...

El método WndProc es el que se encarga de procesar todos los mensajes que recibe un Form y es por eso que ese es el punto indicado para atraparlos.


Ahora el problema esta en conocer el valor de los mensajes, ya que muchas veces uno sabe que mensaje procesar, pero no sabe cual es su valor. Estos valores están definidos en la claseSystem.Windows.Forms.NativeMethods y System.Design.NativeMethods, pero lamentablemente estas clases son internas y no tenemos acceso a ellas, por lo que vamos a tener que usar .NET Reflector para ver su contenido.


La info de este post fue sacada de aquí.


Saludos

MonoDevelop 2.2 Beta 1: We go cross platform.

MonoDevelop goes cross platform.

Since the beginning of time, man has yearned to get a cross platform .NET IDE. Homer's Odyssey described one man's effort to achieve such a thing. And it was not until today, September 9th of 2009 that the world can test out such a tool.

With this release MonoDevelop leaves its cozy Linux nest and embarks on a wild adventure into the hearth of MacOS and Windows. The MonoDevelop team made this one of their major goals for this release: to turn our loved IDE into a cross platform IDE.

If you are curious about the details, check out the What is new in MonoDevelop 2.2 page.



MonoDevelop on Windows

We are not only bringing MonoDevelop to OSX and Windows as a plain GUI port, but we are also providing installers, deep operating system integration and support for native debugging on each platform.



MonoDevelop on MacOS X

In addition to becoming a cross platform IDE, there are many new features in MonoDevelop.

For instance, MonoDevelop can be used to develop ASP.NET MVC applications on OSX and Linux and Silverlight applications on OSX and Linux.

Debugger


MonoDevelop now has integrated debugger support. Not only it is able to debug Mono applications, it also can work as a frontend to GDB to debug native applications.

In addition, on Linux it is possible to debug ASP.NET pages.

New Add-ins


New exciting add-ins: ASP.NET MVC, Silverlight and iPhone (for use with MonoTouch).

Policies


A common problem that we face as open source developers is that not every project uses the same coding style. Different teams use different coding conventions. MonoDevelop now supports policies to describe how files should be edited and what defaults should be used in each:


Editor Improvements


My favorite new feature is Dynamic Abbrev (Alt-/) a feature that we brought from Emacs and that fills me with joy. That being said, for the non-Emacs lovers there are plenty of features that you asked for, and that we implemented:

  • Extensive refactoring support. And I mean, it is extensive.

  • Code templates.

  • On the fly formatting.

  • Acronym Matching in Code Completion

  • XML Documentation Shown in Code Completion

  • VI mode for those users hooked up on VI commands, they can now use those within MonoDevelop.


Another pretty cool feature is the code generation support that is triggered with Alt-Insert. When you press Alt-insert it will popup a context sensitive dialog box that offers a few options of code that could be generated at this point: ToString methods, Equals/GetHashCode methods all based on existing fields and properties.

Why go Cross Platform?


Going cross platform means that developers will have the same tool across all of the operating systems they use: Windows, Mac and Linux.

.NET developers that have been enchanted by OSX will be able to continue developing software with their favorite programming languages while enjoying OSX and will be able to go back and forth between Windows, OSX and Linux as needed. This also means that they can work with developers in other platforms, regardless of the personal choices of other team members.

As many of you know, the number of contributors to a project is linked to the number of users of that project. By expanding our market presence from Linux, we expect to get contributions, fixes, improvements, bug reports, code and add-ins from developers in other platforms.

We intend to make MonoDevelop the Eclipse of the .NET community. Just like Eclipse became the foundation for Java development, we hope that MonoDevelop will become the foundation for .NET development, and hopefully for much more than that.

A multi-system IDE


We are not religious when it comes to supporting other programming languages [1]. We want to embrace not only .NET-based projects like Gtk#, Silverlight, ASP.NET, Boo, C#, F#, Visual Basic and Windows.Forms. We are also embracing other developer platforms like Python, C/C++, Vala, and we want to expand our presence to work with the Flash, PHP, Ruby, Rails, Flex and any other communities that need a cross platform IDE.

[1] we are just religious about the fact that C# is a better programming language to build an IDE than Java is.

Thanks!


This release could not have been possible without the endless nights and the collaborations of our contributors and all of the end users that reported bugs and gave us feedback.

Posted by Miguel de Icaza on 09 Sep 2009

Visita A La Universidad Tecnologica De Gutierrez Zamora

El dia de hoy muy temprano sali para la ciudad de Gtz. Zamora, el asunto una invitacion del ISC. Luis Rizo, para una entrevista, la estancia fue de los mas impresionante el viaje aunque un poco cansado me deja un buen sabor de boca dado que en esta escuela aunque sus ofertas educativas son: - -, tienen mucha vision sobre el sw libre y la aplicacion a casos reales con ellos, me siento muy contento de haber asistido y desde aca, les mando un cordial saludo muchisimas, gracias..

Replicando Datos En Oracle

Introducción


El presente documento muestra la forma de replicar de manera sencilla los datos de una base de datos en oracle hacia otro servidor oracle, mediante el uso de vistas materializadas.


La replicación te permite tener una copia exacta de una base de datos alojada en un servidor (maestro) que se guardará en otro servidor (esclavo). Todas las modificaciones que se hagan en la base de datos del servidor maestro se actualizarán inmediatamente en el servidor esclavo.


Esto no es una copia de seguridad, ya que si borramos una fila en la base de datos maestra, también se borrará en la base de datos esclava.


A continuación tenemos los pasos para instalar y configurar nuestro servidor para replicar datos.



Instalando Oracle.


Para nuestro caso usaremos la de oracle llamada oracle Express Edition, la cual es gratuita para nuestro servidor. Nos dirigimos a la página:


http://www.oracle.com/technology/software/products/database/xe/htdocs/102xewinsoft.html


Y aceptamos los términos de licenciamiento del programa, en este momento descargaremos el producto para posteriormente instalarlo en nuestro sistema.





[caption id="attachment_51" align="aligncenter" width="300" caption="Descargando OracleXE"]Descargando OracleXE[/caption]


Una vez descargado lo instalaremos dando clic derecho en el instalador y eligiendo la opción, abrir.




[caption id="attachment_52" align="aligncenter" width="300" caption="Ejecutando el instalador"]Ejecutando el instalador[/caption]


Esperamos un momento y podremos ver las opciones del programa.




[caption id="attachment_53" align="aligncenter" width="300" caption="Opciones de configuracion"]Opciones de configuracion[/caption]

[caption id="attachment_54" align="aligncenter" width="300" caption="Instalacion OracleXE"]Instalacion OracleXE[/caption]

El programa de instalación nos muestra la pantalla de bienvenida para la instalación, en este momento tenemos que dar click en siguiente.





[caption id="attachment_55" align="aligncenter" width="300" caption="LicenciaDirectorio de instalacion"]Licencia[/caption]


Aceptamos los términos y condiciones del programa y pulsamos siguiente, en seguida seleccionamos la ubicación de los archivos de instalación, si queremos instalarlos en otra ubicación podemos seleccionarla pulsando el botón  Examinar, después de esto pulsamos siguiente.





[caption id="attachment_57" align="aligncenter" width="300" caption="Establecer contraseña"]Establecer contraseña[/caption]


Ahora tecleamos una contraseña para los usuarios SYS y SYSTEM, los cuales son los usuarios (dba) administradores en oracle, y pulsamos en siguiente, ahora nos mostrara un resumen de la instalación si estamos de acuerdo con este daremos clic en instalar.





[caption id="attachment_58" align="aligncenter" width="300" caption="Instalacion"]Instalacion[/caption]

Configurando El Servidor


Ahora editaremos el archivo “C:\oracle\product\10.2.0\db_1\network\admin\tnsnames.ora”, y agregaremos las siguientes líneas de configuración (resaltadas en cursiva y negrita) para que el servidor oracle reconozca nuestro servidor remoto, usando una resolución de nombres tns.
# tnsnames.ora Network Configuration File: D:\oracle\product\10.2.0\db_1\network\admin\tnsnames.ora


# Generated by Oracle configuration tools.

LISTENER_ORCL =

(ADDRESS =

(PROTOCOL = TCP)

(HOST = RAMMSCORP.gateway.2wire.net)

(PORT = 1522)

)

ORCL =

(DESCRIPTION =

(ADDRESS =

(PROTOCOL = TCP)

(HOST = RAMMSCORP.gateway.2wire.net)

(PORT = 1522)

)

(CONNECT_DATA =

(SERVER = DEDICATED)

(SERVICE_NAME = orcl)

)

)

YOS =

(DESCRIPTION =

(ADDRESS_LIST =

(ADDRESS =

(COMMUNITY = TCP)

(PROTOCOL = TCP)

(HOST = yosy1)

(PORT = 1521)

)

)

(CONNECT_DATA =

(SID = XE)

)

)

EXTPROC_CONNECTION_DATA =

(DESCRIPTION =

(ADDRESS_LIST =

(ADDRESS =

(PROTOCOL = IPC)

(KEY = EXTPROC1)

)

)

(CONNECT_DATA =

(SID = PLSExtProc)

(PRESENTATION = RO)

)

)
Donde YOS es el nombre del servidor remoto que agregamos, es decir un alias, PROTOCOL es el protocolo de comunicación hacia el servidor, HOST es el nombre ó la dirección IP de la computadora que tiene el servidor, PORT indica el numero de puerto al cual se conectara el servidor y finalmente SID que es el nombre de servicio del servidor remoto.


De esta manera nos podremos conectar con el servidor remoto usando la nomenclatura de conexión:


Usuario/Password@Alias_Del_Servidor:[Puerto]


Donde Usuario es cualquier usuario valido del servidor remoto, Password es la contraseña del usuario remoto, @Alias_del_servidor es el nombre que hemos añadido en el archivo de configuración tnsnames.ora, y finalmente el Puerto que indica a que puerto se conectara este parámetro es opcional, por defecto las conexiones se realizan al puerto 1521.


Una vez editado y configurado archivo, tendremos que configurar nuestro servidor estableciendo un DBLink ó un enlace a base de datos.


Usando la siguiente instrucción:




Create database link "Nombre_Del_DBLink" connect to Usuario identified by "Password" using 'HOST[: PUERTO]/SID'

De la siguiente instrucción tenemos Nombre_Del_DBLink el cual es un nombre cualquiera para identificar a que base de datos estamos ligados, Usuario el cual debe de ser un usuario remoto valido, Password es la contraseña del usuario remoto, HOST es el nombre ó dirección ip del servidor, PUERTO indica el numero del puerto al que se conectara el parámetro es opcional, el puerto por defecto es el 152, y por ultimo SID es el nombre del servicio al cual se conectara nuestro servidor.


La cual nos proporcionara la facilidad de hacer consultas del tipo:


Objeto@DBLink


Donde Objeto puede ser cualquier tipo de objeto en la base de datos remota y @DBLink es el enlace a la base de datos, de este modo podremos usar las tablas, vistas, triggers y demás objetos en el servidor.


Estos pasos de configuración se hacen en los dos servidores para que se puedan comunicar, es decir tenemos que dar de alta el servidor 1 en el servidor 2 y viceversa; además tenemos que dar de alta un DBLink para cada uno de ellos, una vez teniendo configurados los servidores podremos iniciar la replicación.



Replicando Datos


Ahora antes de replicar los datos tenemos que tener datos, necesitamos tener cuando menos una tabla en la base de datos, ahora crearemos una tabla para hacer esta práctica la cual llamaremos: COMPRAS; la cual estará en el servidor 1 (RAMMS) y será replicada hacia el servidor 2 (YOS). Utilizaremos las sentencias de SQL Plus para crear la tabla con los siguientes campos de la siguiente manera:



CREATE TABLE RAMMS.COMPRAS

(

CODIGO VARCHAR2 (8 BYTE) NOT NULL,

PROVEEDOR VARCHAR2 (30 BYTE) NOT NULL,

PRODUCTO VARCHAR2 (45 BYTE) NOT NULL,

PRECIOCOMPRA INTEGER NOT NULL,

PRECIOVENTA INTEGER NOT NULL,

CANTIDAD NUMBER NOT NULL

)

Y posteriormente:
ALTER TABLE RAMMS.COMPRAS ADD (

PRIMARY KEY

(CODIGO)

USING INDEX

TABLESPACE USERS

PCTFREE    10

INITRANS   2

MAXTRANS   255

STORAGE    (

INITIAL          64K

MINEXTENTS       1

MAXEXTENTS       UNLIMITED

PCTINCREASE      0

));

Después de crear la tabla agregaremos datos en ella, quedando de la siguiente manera:


Ahora realizaremos una consulta desde el servidor 2 (YOS) usando los DBLink, quedando de la siguiente manera:




[caption id="attachment_50" align="aligncenter" width="300" caption="Datos"]Datos[/caption]
SELECT * FROM COMPRAS@DBLINKRAMMS

Arrojando la siguiente información:

[caption id="attachment_50" align="aligncenter" width="300" caption="Datos"]Datos[/caption]

Como podemos observar la consulta funciona es decir que podemos consultar objetos desde el servidor 2, ahora crearemos en el servidor 1 (RAMMS), una tabla LOG para la replicación de la tabla COMPRAS, con la siguiente instrucción:



CREATE MATERIALIZED VIEW LOG ON RAMMS.COMPRAS

NOCACHE

LOGGING

NOPARALLEL;


Esta tabla guardara los datos cambiados y actualizara de manera instantánea todas las replicas de la tabla COMPRAS.


Ahora desde el servidor 2 (YOS) crearemos nuestra vista materializada para recibir los datos de la tabla original, a este procedimiento de replica se le denomina replica en forma de instantánea o de snapshot, lo haremos usando la siguiente instrucción.



CREATE MATERIALIZED VIEW RAMMS.COMPRAS

BUILD IMMEDIATE

REFRESH FAST ON COMMIT

AS

SELECT * FROM COMPRAS@DBLINKRAMMS;

Ahora en el servidor 2 (YOS), ya disponemos de una copia exacta de la tabla compras del servidor 1 (RAMMS), y se actualizara automáticamente cuando se haga un commit en las transacciones, ahora podemos ejecutar la sentencia:



SELECT * FROM COMPRAS;

E inmediatamente después podremos apreciar el resultado de la consulta, nótese que en el servidor 2,no existían datos para la tabla COMPRAS de hecho COMPRAS no es una tabla es una ¡vista!







[caption id="attachment_50" align="aligncenter" width="300" caption="Datos"]
Datos[/caption]




De esta manera cualquier cambio realizado en el servidor 1, se verá reflejado inmediatamente en el servidor 2, de esta manera tenemos la información actualizada y lo más importante distribuida en varios nodos al mismo tiempo.



Conclusión


En esta práctica aprendimos a hacer una replicación de instantánea de una tabla en oracle usando dos servidores uno que es el servidor que tiene la tabla a replicar (RAMMS) y un cliente (YOS)  el cual puede tener los datos de la tabla para consultar, cabe señalar que la vista materializada es de solo lectura, debido a que es una instantánea, también configuramos los accesos de los servidores mediante el archivo de configuración tnsnames.ora y dimos de alta los servidores en los archivos, lo que nos daba como resultado la comunicación entre ambos y logrando así poder generar el enlace de base de datos entre ellos. Teniendo la posibilidad de realizar consultas distribuidas entre los servidores. Finalizando en la creación de la tabla de LOGS y la vista materializada, para poder consultar los datos replicados de manera local.


Documento en Scribd ó ¡Descargalo!

SELECT TOP 1 song FROM youtube ORDER BY NEWID() --Links 2 3 4

Bueno este es un video aleatorio del youtube que me gusta mucho es links 2 3 4, de rammstein espero les guste... Mi parte favorita es cuando batallon de hormiguitas va a partirles su madre a los escarabajos malditos, y sobre todo el mensaje de trabajo en equipo de las hormiguillas, es realmente una de las mejores canciones de este grup, aleman llena de poder y fuerza en los acordes de la canción.





Simplemente impresionante, espero y lo disfruten, xD!!

Localización Geografíca Por IP Usando SQL Server

Introducción


En Internet es el concepto del sitio web de análisis para facilitar el seguimiento de todos los visitantes las actividades y patrones de uso. Una de las dimensiones de la pista es la información geográfica de los visitantes, que puede obtenerse usando la dirección IP de la información que se recoge cuando un usuario entra en una página web. En este artículo describiremos un proceso simple que permite a su sistema de información mostrar la información geográfica de los visitantes.



Ámbito


Este artículo no describe el proceso necesario para capturar la información IP del usuario. Este proceso es una solución a nivel de las aplicaciones que se pueden construir con ASP.NET, PHP, JSP, Python, Ruby, etc. El ámbito de aplicación de este artículo se limita a la utilización de la dirección IP para descubrir los datos geográficos. Estos datos se compone del País, región, ciudad, código postal y el código de área cuando corresponda. Algunos países no tienen el concepto de código postal. :s



¿Qué es una dirección IP?


Cuando un usuario entra en una página web, la aplicación web tiene la capacidad para recopilar información de este usuario. Uno de estos elementos de datos es la dirección IP. La dirección IP tiene un formato de xxx.xxx.xxx.xxx( de 4 octetos separados por puntos ej. 189.23.45.21), y es una dirección lógica asignada a un dispositivo. Esto es lo que identifica a su dirección de Internet, y está compuesto de segmentos que identifican su ubicación geográfica.



¿Qué necesito para mapear una dirección IP a una ubicación geográfica?


Para asignar la dirección IP a una representación geográfica, el sistema de mapeo de los datos geográficos necesita informacion sobre sus ubicaciones. Esta información es proporcionada por varias empresas. En este caso, nosotros estamos usando el GEOLiteCity datos, que es gratuito. Para obtener estos datos, visite aqui y descargar el archivo ZIP que contiene dos archivos, bloques y ubicación CSV(comma separate value). El archivo de mapas de un bloque de números IP a una ubicación. El archivo tiene la ubicación de información geográfica. Tenga en cuenta que hay frecuentes cambios a estos archivos, de modo que asegúrese de leer la descripción de sus servicios.



Para importar estos datos a su base de datos, primero debe crear la tabla de definiciones. Nosotros necesitamos crear el Bloque Ubicación geográfica y tablas. Esta es la tabla de definiciones: (también puede descargar scripts(las secuencias de comandos)).




[caption id="attachment_20" align="alignnone" width="461" caption="tablas"]tablas[/caption]

Puedes importar los datos a través de su método preferido. La primera línea en el archivo CSV es una declaración de derechos de autor. La segunda línea de la cabecera de la columna, así que asegúrese de eliminar o pasar por alto  la primera línea durante el proceso de importación. También he incluido una tabla de registro de visitantes que pueden ser utilizados para rastrear la información del usuario. Esta tabla es muy simple, y no incluye todos los posibles elementos de datos que pueden ser recogidos.


Para simplificar el proceso de imporatacion de datos podemos ejecutar un BULK INSERT, usando la sentencia:




BULK INSERT GeoLiteCity_Location
FROM 'GeoLiteCity-Location.csv'
WITH
(
FIELDTERMINATOR = ',',
ROWTERMINATOR = '0x0a',
KEEPNULLS)
GO

BULK INSERT GeoLiteCity_Blocks
FROM 'GeoLiteCity-Blocks.csv'
WITH
(
FIELDTERMINATOR = ',',
ROWTERMINATOR = '0x0a',
KEEPNULLS)
GO

Esto tarda un poco puesto que son cerca de 85000 registros por tabla, jeje en fin, Seguimos.




Solución


Una vez que los datos se ha importado, te darás cuenta de que la dirección IP en los datos no se ve nada parecido 192.15.10.125. La información se almacena realmente como un número de IP. Este valor numérico es lo que nos permite hacer una serie de comparación. Una serie de números IP se asigna a una determinada ubicación. Esto es lo que nos permite hacer la asociación, pero el primer paso es averiguar cómo convertir una dirección IP a un número IP. Aquí es donde una función definida por el usuario nos puede ayudar. Primero tenemos que convertir la dirección IP a un número de IP usando la función ConvertIP2Num a continuación:



CREATE function dbo.ConvertIp2Num(@ip nvarchar(15))
returns bigint
as
begin

declare @delimiter NVARCHAR(1), @SUBNET_MASK INT

set @delimiter = '.'
set @SUBNET_MASK = 256

DECLARE @textXML XML;
SELECT    @textXML = CAST('<col>' + REPLACE(@ip, @delimiter, '</col><col>') + '</col>' AS XML);

DECLARE @idx int, @ipNum float
SET @idx = 4
SET @ipNum = 0

declare @segments table(id int ,col int)
INSERT INTO @segments(id, col)
--reorder the sections. must start from the right segment (4 to 1)
SELECT  ROW_NUMBER () OVER (ORDER BY col) as id,
T.col.value('.', 'int') as col
FROM    @textXML.nodes('/col') T(col)
order by id desc

--convert segments to number
select  @ipNum = @ipNum + (cast((col % @SUBNET_MASK) as float) * power(@SUBNET_MASK,@idx-id))
from @segments

return cast(@ipNum as bigint)
end

sqleros.com.arEjemploGeolocalizacionGO


Esta función primero la dirección IP se divide en cuatro segmentos (delimitado por un punto). Aquí es donde realmente el XML se convierte en la mano. Acabamos de crear una cadena XML y utilizar el analizador para hacer la división para nosotros por la selección de los nodos XML. Usamos el Row_Number () para crear un factor que nos ayudará a llegar al segmento de peso (es decir, el segmento: 192 ha RowNumber: 1 y con un peso de: 4-1 = 3). Ahora aplicar la fórmula de conversión, que consiste en la asignación de una base cero peso a cada segmento (cero a partir de la serie de sesiones de la derecha) y multiplicando por este segmento (256 ^ n) o potencia (256, n) donde n = peso. El último paso es añadir todos los resultados del segmento. Por ejemplo, IP 192.15.10.125 se convierte de la siguiente manera:





[caption id="attachment_29" align="alignnone" width="270" caption="Conversion de ip"]Conversion de ip[/caption]


El resultado es el número que se puede utilizar para la consulta geográfica tablas. Para ello, puede crear una consulta similar a la de debajo de la cual devuelve la información geográfica.






[caption id="attachment_31" align="alignnone" width="459" caption="Resultado"]Resultado[/caption]

Conclusión:


Con este artículo, tuve la oportunidad de mostrar de un simple proceso de crear su propia base de datos de GEO buscar y dar solución a un mapa de la dirección IP a su información de ubicación. Todavía hay otros elementos a considerar como automatizar el proceso de importación para descargar los nuevos archivos, convertir la dirección IP a valor en numeros , integrar esta información en un almacén de datos, y crear informes que muestran su equipo de marketing en las regiones lo que los clientes están ubicados.


Fuente original en ingles Arhivos adicionales



Esta función primero la dirección IP se divide en cuatro segmentos (delimitado por un punto). Aquí es donde realmente el XML se convierte en la mano. Acabamos de crear una cadena XML y utilizar el analizador para hacer la división para nosotros por la selección de los nodos XML. Usamos el Row_Number () para crear un factor que nos ayudará a llegar al segmento de peso (es decir, el segmento: 192 ha RowNumber: 1 y con un peso de: 4-1 = 3). Ahora aplicar la fórmula de conversión, que consiste en la asignación de una base cero peso a cada segmento (cero a partir de la serie de sesiones de la derecha) y multiplicando por este segmento (256 ^ n) o potencia (256, n) donde n = peso. El último paso es añadir todos los resultados del segmento. Por ejemplo, IP 192.15.10.125 se convierte de la siguiente manera: