Introduction
El servidor fue creado en C# en modo consola. El servidor comienza a escuchar conecciones en el puerto 5050 Puede soportar 100 conecciones. El funcionemiento es como sigue:
Details
- El servidor comienza a escuchar por conecciones.
- Si hay una conección, el servidor inicia un hilo para manejar a ese cliente
- El servidor guarda la información del cliente y crea un id unico para el. Envia un mensaje XML de bienvenida al Cliente.
- El servidor queda en espera de instrucciones desde el cliente.
Mensajes
El servidor solo puede enviar mensajes XML, o archivos de Video (virtualmente cualquier archivo). El servidor solo acepta comunicaciones en formato XML
Los mensajes XML tienen el siguiente formato:
<?xml version="1.0" encoding="utf-8"?>
<Mensaje xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Tipo>TIPO_DEL_MENSAJE</Tipo>
<contenido>TEXTO_DEL_MENSAJE</contenido>
<clientID>7ID_DEL_CLIENTE</clientID>
</Mensaje>- TIPO_DEL_MENSAJE : Puede ser MSG, LIST, VIDEO o IMG
- MSG : Es el tipo genérico de mensaje XML
- LIST: Es una instrucción de solicitud de Listado de Videos al servidor.
- VIDEO: Es una instrucción de solicitu de un VIDEO especifico, en este caso en TEXTO_DEL_MENSAJE debe ir el id del video solicitado.
- ID_DEL_CLIENTE: Es un identificador único para cada cliente, el cliente obtiene este id desde el mensaje de Bienvenida del servidor.
¿Como funciona el envío desde el servidor?
El servidor envía todo tipo de mensajes basado en el envío de un archivo. Para esto el servidor lee en forma binaria el archivo X Luego envia al Cliente un array de bytes de tamaño 4 indicando el tamaño del archivo a recibir (el cliente recibe). Después envía en trozos el archivo, por lo que el cliente debe recibir dicha información de la misma manera. A modo de ejemplo aquí está el código que el Cliente usa para recibir información y como Enviar.
private byte[] Recibir(Socket s){
int total = 0;
int recv;
int b = IPAddress.NetworkToHostOrder(4);
byte[] datasize = new byte[b];
if(s.Connected){
recv = s.Receive(datasize, 0, 4, 0);//recibe el tamaño de lo que se recibira
int size = BitConverter.ToInt32(datasize, 0);
int dataleft = IPAddress.NetworkToHostOrder(size);
byte[] data = new byte[IPAddress.NetworkToHostOrder(size)];
size = dataleft;
Console.WriteLine("Se recibiran "+size);
while (total < size){
try
{
recv = s.Receive(data, total, dataleft, 0);
if (recv == 0)
{
break;
}//if
total += recv;
dataleft -= recv;
}
catch (Exception e)
{
Console.WriteLine("Error:" + e.Message);
Guid id = findKey(s);
cleanFiles(id);
break;
}
}//while
return data;
}else{
Guid id = findKey(s);
cleanFiles(id);
throw new Exception("Cliente Desconectado");
}
}//RecibirUna vez recibido el array bytes se debe manipular para escribir el fichero recibido. Un ejemplo en C# para guardar un mensaje XML
byte[] recibido = Recibir(sender); //recibir
Stream st = new MemoryStream(recibido);//tenemos el Stream
String content = Encoding.UTF8.GetString(recibido);
Mensaje msg = Mensaje.Deserialize(st);
Mensaje es una clase que contiene el formato de los mensajes XML, esta se puede Serializar o Deserializar (convertir desde un Objeto a XML o desde XML a Objeto como en este caso)
Para enviar el cliente ejecuta la siguiente instruccion
/*
* Metodo para el envio por medio del socket
* @param Socket socket del cliente
* @param FileStream para lectura y envio
*/
private void Send(Guid id, FileStream fs){
Socket socket = (Socket)clientsTable[id]; //obtiene el socket del cliente
if(socket.Connected){
byte[] data = ReadFully(fs);
int total = 0;
int size = data.Length;
int dataleft = size;
int sent;
byte[] datasize = new byte[4];
datasize = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(size));
try
{
sent = socket.Send(datasize); //envia tamaño del archivo
while (total < size) //Comienza el envio
{
try
{
sent = socket.Send(data, total, dataleft, SocketFlags.None);
total += sent;
dataleft -= sent;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
cleanFiles(id);
break;
}
}//while
}
catch (Exception e)
{
Console.WriteLine(e.Message);
cleanFiles(id);
}
}else{
Console.WriteLine("Error");
cleanFiles(id);
}
}//SendPara enviar el listado de videos se usa un metodo similar al de los mensajes. Se serializa un lsitado de objetos tipo VideoList
[XmlRoot("Listado")]
public class VideoList
{
[XmlElement("Titulo")]
public String titulo;
[XmlEnum("Duracion")]
public String duracion;
[XmlElement("id")]
public int id;
[XmlElement("Imagen")]
public String codigo_imagen;
[XmlElement("Path")]
public String path;
public VideoList ()
{
}
public void show(){
Console.WriteLine("Titulo: "+titulo);
Console.Write("\t Duracion: "+duracion+" | Id: "+id);
Console.WriteLine("\t Path: "+path);
}
}Para serializarlo
/* Metodo para la serializacion del listado de videos*/
private FileStream SerializeList(List<VideoList> listado, Guid id_cliente){
XmlSerializer serializer = new XmlSerializer(typeof(List<VideoList>));
FileStream f = new FileStream("/xml/listado"+id_cliente+".xml",FileMode.Create,FileAccess.Write,FileShare.ReadWrite);
TextWriter tw = new StreamWriter(f);
serializer.Serialize(tw,listado);
tw.Close();
return f;
}//SerializeList