Pasar objetos por red en C#

Iniciado por arenoide, 7 Septiembre 2011, 01:40 AM

0 Miembros y 1 Visitante están viendo este tema.

arenoide

Hola, veréis,

Estoy haciendo un programa en C# que necesito que hable con otro programa que crearé para otro ordenador. De forma que mi programa cliente le mande información por red al programa servidor, y el programa servidor le conteste. Algo así como un chat, solo que necesito en vez de pasarle strings, pasarle directamente objetos que yo previamente haya predefinido en ambos. El programa servidor cogerá esos objetos, los modificará y me los mandará de vuelta.Esa sería más o menos la idea.

He estado googlelando pero no encuentro nada de pasar objetos por red.
Alguien me puede arrojar un poco de luz sobre este tema?

Muchas gracias de antemano.

Novlucker

Contribuye con la limpieza del foro, reporta los "casos perdidos" a un MOD XD

"Hay dos cosas infinitas: el Universo y la estupidez  humana. Y de la primera no estoy muy seguro."
Albert Einstein

seba123neo

como dijeron, serializacion binaria seria la solución, aca un post perfecto con la solución.

c# send recive object over network?

saludos.
La característica extraordinaria de las leyes de la física es que se aplican en todos lados, sea que tú elijas o no creer en ellas. Lo bueno de las ciencias es que siempre tienen la verdad, quieras creerla o no.

Neil deGrasse Tyson

arenoide

Muchísimas gracias a ambos :)

Voy a echarle un vistazo más detenidamente, pero tiene muy buena pinta.

arenoide

#4
Hola,

Veréis, he estado intentando seguir el siguiente link, para hacer el serializador-deserializador.
http://www.codeproject.com/KB/cs/objserial.aspx

Estoy probando primero serializando a archivo. Esto me está generando un fichero tal que así:
   ÿÿÿÿ          =Serializacion, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null   Serializacion.Employee   EmpIdEmpName   
     Omkumar


Cuando dentro de un mismo proyecto, serializo y deserializo no hay problema.

El problema está cuando intento deserializarlo desde otro proyecto de distinto nombre. Por ejemplo, el proyecto que serializa lo llamo "Serializacion" y el que deserializa "Deserializacion". Pues parece que Deserialización se lia al intentar deserializar el archivo y me lanza la siguiente excepción:
No se puede encontrar el ensamblado 'Serializacion, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'

y pienso que es porque dentro del archivo se ha insertado el nombre del proyecto entre otras cosas. Cómo podría hacerlo para que diera igual el nombre del proyecto de origen y que lo deserializara todo correctamente?

Alguna idea?
Muchas gracias.

arenoide

#5
Hola, finalmente encontré cómo enviar objetos entre 2 programas cuyos nombres sean distintos. Hay que hacerlo serializando en XML en vez de en binario, aquí dejo el código por si alguien en el futuro tiene mi mismo problema.
He seguido el siguiente link, solo que con algunas modificaciones:
http://www.codeproject.com/KB/cs/objserial.aspx

Código para el cliente:
Código (csharp) [Seleccionar]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Xml.Serialization;
using System.Data.SqlTypes;

namespace Cliente
{
   class Program
   {
       static void Main(string[] args)
       {
           RunClient("127.0.0.1", 6666);
       }

       public static void RunClient(string SrvIP, int SrvPort)
       {
           object obj = null;
           XmlSerializer xmls = new XmlSerializer(typeof(Employee));
           try
           {
               var tcpclnt = new TcpClient();
               Console.WriteLine("Connecting.....");
               tcpclnt.Connect(SrvIP, SrvPort);
               Console.WriteLine("Connected");

               Stream stm = tcpclnt.GetStream();
             
               Employee mp = new Employee();
               mp.EmpId = 10;
               mp.EmpName = "Omkumar";
               byte[] b = new byte[10000];
               Stream st = new MemoryStream(b);

               Console.WriteLine("Enviando Informacion...");
               xmls.Serialize(st, mp);

               stm.Write(b, 0, b.Length);

               var bb = new byte[10000];

               var k = stm.Read(bb, 0, bb.Length);

               for (var i = 0; i < k; i++)
                   Console.Write(Convert.ToChar(bb[i]));

               Console.ReadLine();

               tcpclnt.Close();
           }

           catch (Exception e)
           {
               Console.WriteLine("Error..... " + e.StackTrace);
               Console.ReadLine();
           }

       }
   }
}



Código para el Servidor
Código (csharp) [Seleccionar]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Xml.Serialization;
using System.Data.SqlTypes;

namespace Servidor
{
   class Program
   {
       static void Main(string[] args)
       {
         
           RunServer("127.0.0.1",6666);
       }

       public static void RunServer(string SrvIP, int SrvPort)
       {
           try
           {
               var ipAd = IPAddress.Parse(SrvIP);
               XmlSerializer xmls = new XmlSerializer(typeof(Employee));

               /* Initializes the Listener */
               if (ipAd != null)
               {
                   var myList = new TcpListener(ipAd, SrvPort);

                   /* Start Listening at the specified port */
                   myList.Start();
                   
                   Console.WriteLine("El servidor se está ejecutando en el puerto: " + myList.LocalEndpoint);
                   Console.WriteLine("Esperando conexion...");
                   
                   var hacen = new ASCIIEncoding();
                   Employee mp = null;

                   while (true)
                   {
                       Socket s = myList.AcceptSocket();
                       Console.WriteLine("Conexion aceptada de: " + s.RemoteEndPoint);
                       var b = new byte[10000];
                       Stream stream = new MemoryStream(b);
                       int k = s.Receive(b);
                       Console.WriteLine("Informacion recibida. Deserializando...");
                       mp = (Employee)xmls.Deserialize(stream);
                       stream.Close();
                       Console.WriteLine("Deserializado correcto");
                       s.Send(hacen.GetBytes("Mensaje recibido"));
                       Console.WriteLine("Employee Id: {0}", mp.EmpId.ToString());
                       Console.WriteLine("Employee Name: {0}", mp.EmpName);
                       s.Close();
                       Console.ReadLine();
                   }

                   myList.Stop();
               }
           }
           catch (Exception e)
           {
               Console.WriteLine("Error..... " + e.StackTrace);
           }
       }
   }
}



Este es el codigo para la clase que ambos programas deben de tener:
Código (csharp) [Seleccionar]

using System;

namespace Cliente
{
   [Serializable()] //Set this attribute to all the classes that you define to be serialized
   public class Employee
   {
       public int EmpId;
       public string EmpName;

       //Default constructor
       public Employee()
       {
           EmpId = 10;
           EmpName = "Periquito";
       }
   }
}


Lo he copiado casi en el momento en que me ha funcionado, así que puede que haya código que sobre y demás, pero funcionar funciona.

Saludos.

oz64

Otra forma aparte de enviar objetos serializados en forma binaria entre dos programas cuyos nombres sean distintos es tener las clases para serializar  en librerias (.dll) ya q igual tenemos q tener esas clases en el servidor como en el cliente, teniendolo en forma de libreria solo nos hace falta referenciar al proyecto para su uso y asi se los puede usar sin tener el problema de los diferentes nombres en los proyectos.

Salu2...!!!