Servidor socket TCP C#

Iniciado por FanAdmin, 24 Julio 2017, 22:46 PM

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

FanAdmin

OPTÉ POR DEJAR ESTE TOPIC

Buenas, estoy creando un Cliente via Sockets en AS3, y su respectivo servidor en C#...
Funciona bien solo que el servidor C# solo lee la primera entrada que le envía el cliente al iniciar la conexión cliente servidor.
Luego el Cliente si envía packets, el servidor ya no lo escucha...
Y aquí les dejo el código:


ENTRADA PRINCIPAL DEL PROGRAMA EN C# CONSOLA
using System;
using SnapServer.SaptConn.Network;
using System.Net.Sockets;
using System.Net;

namespace SaptServer
{
   class Program
   {
       public const int Port = 8888;
       public static string[] ClientsOnline;
       static void Main(string[] args)
       {
           Server server = new Server();
           Server.serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
           Server.serverSocket.Bind(new IPEndPoint(IPAddress.Any, Port));
           Server.serverSocket.Listen(999);

           Console.WriteLine(".:|_serVerYork_|:.");
           server.Start();
       }
   }
}



SERVER.CS
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace
{
   class Server
   {
       public static Socket serverSocket, clientSocket;
       private byte[] buffer;

       public void Start()
       {
           clientSocket = serverSocket.Accept();
           buffer = new byte[clientSocket.ReceiveBufferSize];
           while (clientSocket.Available == 0)
           {
               receiveData();
           }
       }

       private void receiveData()
       {
               try
               {
                   int received = clientSocket.Receive(buffer);
                   if (received != 0)
                   {
                       Array.Resize(ref buffer, received);
                       string receivedMsg = UTF8Encoding.UTF8.GetString(buffer);
                       Array.Resize(ref buffer, clientSocket.ReceiveBufferSize);
                       if(receivedMsg.Contains("policy-file-request"))
                       {
                           if(Clients.OrganizarClientes(Convert.ToString(clientSocket.LocalEndPoint)))
                           {
                               sendMsg("<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"8888\" /></cross-domain-policy>");
                               clientSocket.Close();
                               Start();
                           } else {
                               Console.WriteLine("Nuevo cliente: " + clientSocket.LocalEndPoint);
                               sendMsg("<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"8888\" /></cross-domain-policy>");
                               clientSocket.Close();
                               Start();
                           }
                       } else {
                           Console.WriteLine("Cliente_" + clientSocket.LocalEndPoint + ": " + receivedMsg);
                           Messages.Messages.ClasificarMsg(receivedMsg);
                           Start();
                       }
                   } else { return; }
               } catch (Exception ex){}
           
           receiveData();
       }

       public static void sendMsg(string data)
       {
           clientSocket.Send(UTF8Encoding.UTF8.GetBytes(data));
           
       }
   }
}

// RESPONDO EL XML YA QUE EL SOCKET AS3 NECESITA EL ARCHIVO XML PARA PASAR POR EL PUERTO Y/O DOMINIO ASIGNADO EN EL XML...


CLIENTS.CS
using System;
using System.Collections.Generic;

namespace
{
   public class Clients
   {
       public static bool OrganizarClientes(string data)
       {
           string[] tmpStr = data.Split(':');
           List<string> tmpList = new List<string>();
           bool tmpBool = false;
           try
           {
               for (int i = 0; i < Program.ClientsOnline.Length; i++)
               {
                   tmpList.Add(Program.ClientsOnline[i]);
                   if (!(Program.ClientsOnline[i] == tmpStr[0])){ tmpBool = false; } else { tmpBool = true; break; }
               }
           }catch(Exception ex) { tmpBool = false; }
           if (tmpBool)
           {
               return true;
           }else { tmpList.Add(tmpStr[0]); Program.ClientsOnline = tmpList.ToArray(); return false; }
       }
   }
}



MESSAGES.CS
using System;

namespace
{
   class Messages
   {
       public static void ClasificarMsg(string data)
       {
           switch (data)
           {
               case ("Conexión establecida"):
                   Server.sendMsg("GoToLogin");
                   Console.WriteLine("Server: " + "GoToLogin");
                   break;

                //else else...
           }
       }
   }
}



CLIENTE AS3:

var newSocket:Socket; // <- El tipo de Socket en AS3
newSocket = new Socket("IP", 8888);
newSocket.addEvent....
....


Quisiera saber que me recomendarían para este tipo de proyectos! Se acepta cualquier sugerencia... Saludos!


· Tema movido C# no es parte de C/C++, es .NET
>aquí las reglas del foro
-Engel Lex

ivancea96

Hay varias cosas que deberías reestructurar.
Una de ellas es que creas el serverSocket desde fuera. Sería más correcto que lo creases, bindeases y lo pusieras a escuchar dentro del método Start, pasándole los parámetros. Pero bueno, esto es secundario actualmente.

El principal problema es el Start y el receiveData. ReceiveData es una función recursiva. ¿Por qué? Dentro del Start la llamas en bucle, para qué hacerla recursiva. Sería preferible cambiar la recursión por un bucle. Y bueno, no solo es recursiva sino que llama a Start. Este flujo pues... ¿Esperas que la función "receiveData" acepte a otros clientes? Si quieres que tras un cliente, espere a otro, entonces pon un bucle dentro de la función Start, por ejemplo.

Y luego, en la función Start, tienes un bucle que es "while(Available == 0)". Mientras que no haya datos, leemos datos. ¿Y qué ocurre si cuando llegamos a este punto ya hay datos?

FanAdmin

#2
Intenté cambiar el código pero sigue resultando lo mismo...

Nuevo SERVER.CS:
Código (csharp) [Seleccionar]
using System;
using System.Net;
using System.Text;
namespace
{
   class Server
   {
       public static Socket serverSocket, clientSocket;
       public const int Port = 8888;
       private byte[] buffer;

       public void Start()
       {
           //Server server = new Server();
           //Server.serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
           //Server.serverSocket.Bind(new IPEndPoint(IPAddress.Any, Port));
           Server.serverSocket.Listen(999);
           clientSocket = serverSocket.Accept();
           buffer = new byte[clientSocket.ReceiveBufferSize];
           while (buffer.Length > 0)
           {
               try
               {
                   int received = clientSocket.Receive(buffer);
                   if (received != 0)
                   {
                       Array.Resize(ref buffer, received);
                       string receivedMsg = UTF8Encoding.UTF8.GetString(buffer);
                       Array.Resize(ref buffer, clientSocket.ReceiveBufferSize);
                       if (receivedMsg.Contains("policy-file-request"))
                       {
                           if (Clients.OrganizarClientes(Convert.ToString(clientSocket.LocalEndPoint)))
                           {
                               sendMsg("<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"8888\" /></cross-domain-policy>");
                               clientSocket.Close();
                               Start();
                           }
                           else
                           {
                               Console.WriteLine("Nuevo cliente: " + clientSocket.LocalEndPoint);
                               sendMsg("<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"8888\" /></cross-domain-policy>");
                               clientSocket.Close();
                               Start();
                           }
                       }
                       else
                       {
                           Console.WriteLine("Cliente" + clientSocket.LocalEndPoint + ": " + receivedMsg);
                           Messages.Messages.ClasificarMsg(receivedMsg);
                           Start();
                       }
                   }
                   else { return; }
               }
               catch (Exception ex) { }
           } Start();
       }

       public static void sendMsg(string data)
       {
           clientSocket.Send(UTF8Encoding.UTF8.GetBytes(data));
           
       }
   }
}


Lo que ocurre en el emulador al ejecutarlo e iniciar el cliente es:

Nuevo Cliente: IP:8888
Cliente: Conexión establecida
Servidor: TestMensaje

Y en el Cliente se visualiza el mensaje "TestMensaje"...

Pero en cambio, el cliente envía un packet cada 1 segundo, pero no se visualiza en el servidor...

ivancea96

Si esque no has cambiado casi nada, solo un par de líneas. El resto, ha sido meter la función antigua (que estaba bien, salvo algunas correcciones) en la funcion Start. Sepáralas de nuevo, es bueno separar el código en funciones. Pero hayq eu distinguir bien qué es exactamente lo que va a hacer cada función.
Tu función receiveData lo que hacía era recibir los datos, bien, y cerrar el socket y pedir otro cliente y recibir sus datos y etc...
Eso no es una función con una utilidad clara.

Limítate a hacer, por ejemplo, esto:
Start: Bucle { aceptar cliente, trabajar los datos de ese cliente (llamando a receiveData }
ReceiveData: Enviar y recibir datos. Nada más (no llamas a Start ni llamas recursivamente a receiveData. Si quieres recibir más datos o esperar, si tal, harás un bucle


En fin, el resumen de esto es que los métodos deben tener una utilidad clara. Métodos que se llaman de forma circular (Start -> ReceiveData -> Start) pueden ser peligrosos, y en este caso en concreto, no es el momento de usarlo. Divide la función Start en pasos: Recibir cliente, manejar el cliente. Luego, si algún paso es grande (Manejar el cliente), lo mueves a un método privado. Luego, divide y analiza ese método privado.

Rekt

Esperas saber programar un boombang desde 0 sin saber nisiquiera como funciona un bucle?  :silbar:.
Tu problema principal es que solo lees una vez lo que el cliente te envía y que estas reinventando la rueda.

AlbertoBSD

Cita de: Rekt en  2 Septiembre 2017, 17:06 PM
Tu problema principal es que solo lees una vez lo que el cliente te envía y que estas reinventando la rueda.

Opinaria lo mismo que Rekt sobre reinventar la Rueda, C# generalemente ya tiene una API para cualquier cosa, Enviar correso, Enviar peticiones WEB, SQL etc... etc...

Si programas desde 0 (Reinventando la Rueda) Esta bien con fines didacticos e incluso siento yo que aprendes mejor. Pero si te faltan bases sobre como funcionan los ciclos e incluso como funcionan las conexiones TCP/IP entre otros puede salir contraproducente. Te puedes confundir muy facilmente e incluso terminar Frustrado.

Saludos!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

FanAdmin

Cita de: Rekt en  2 Septiembre 2017, 17:06 PM
Esperas saber programar un boombang desde 0 sin saber nisiquiera como funciona un bucle?  :silbar:.
Tu problema principal es que solo lees una vez lo que el cliente te envía y que estas reinventando la rueda.

Buenas tardes, no se bien a qué te refieres, soy sincero, lo único que hice es buscar conexiones de sockets para mí app en Google.
Si así mismo, eso me sucedía, pero ya opte por dejarlo. Saludos!

FanAdmin

Cita de: AlbertoBSD en  2 Septiembre 2017, 17:19 PM
Opinaria lo mismo que Rekt sobre reinventar la Rueda, C# generalemente ya tiene una API para cualquier cosa, Enviar correso, Enviar peticiones WEB, SQL etc... etc...

Si programas desde 0 (Reinventando la Rueda) Esta bien con fines didacticos e incluso siento yo que aprendes mejor. Pero si te faltan bases sobre como funcionan los ciclos e incluso como funcionan las conexiones TCP/IP entre otros puede salir contraproducente. Te puedes confundir muy facilmente e incluso terminar Frustrado.

Saludos!

Buenas tardes, si estoy de acuerdo con ustedes dos, fue una mala idea meterme con conexiones TCP vía sockets a primera vista sin entender su funcionamiento, por esto opte por estudiar de 0 como me lo planteaste y poco a poco voy entendiendo mejor. Saludos!!