2011-03-16 10 views
6

Estoy trabajando en un "sistema de aplicación", donde también tengo que hacer una aplicación de servidor. Estoy trabajando en C# (.NET 4.0). El servidor recogerá principalmente datos de diferentes aplicaciones/clientes de punto de venta (que deberían ser de alrededor de 50-100, pero el servidor también debería ser capaz de atender entre 200 y 300 clientes). Desde un único cliente, un servidor probablemente recibirá alrededor de 1 KB aproximadamente 100 veces por día. El servidor principalmente necesita aceptar los datos, descifrarlos y almacenarlos en el disco. También debería verificar los cambios en el directorio específico para enviar nuevas configuraciones a los clientes, lo que no debería ser muy frecuente.Ayuda con el servidor TCP controlado por evento

Soy bastante nuevo en C# y en la programación del servidor, así que por favor tengan paciencia conmigo. Pensé en usar los métodos threadlinking y async (hay un buen ejemplo de eso en un libro "C# in un nutshell"). Pero dedico bastante tiempo a buscar la mejor solución y encontré esto. Pero el multihilo trae más problemas que beneficios en mi caso. Por lo tanto, pensé en el servidor incluso impulsado. "Un solo proceso, maneja cada evento (conexión aceptada, datos disponibles para leer, puede escribir al cliente, ...) en una devolución de llamada". de "what is event driven web server". Encuentro que la mejor solución para mi problema.

Pero no tengo idea de cómo codificarlo, no pude encontrar ningún ejemplo sobre los servidores controlados por eventos. Por lo que yo entiendo, debería hacer un hilo (+1 para GUI), luego crear un oyente TCP y de alguna manera crear eventos para que cuando el oyente TCP pueda aceptar un cliente el evento active y active el servidor, también cuando los datos para leer de los clientes estaría disponible despertaría el servidor.

Por favor, ayúdame a codificar esto, estoy totalmente perdido. Sé cómo podría hacer esto usando

while(true) 
{ 
    check if client wants to connect 
     accept client and add it to client list 
    iterate through client list and check if anyone is sending data ... 
     accept data and store it 
    ... 
    } 

Pero eso no se basa en eventos y está desperdiciando CPU. El servidor no estará muy activo, por lo que me gustaría que sea lo más eficiente posible.

Algunos ejemplos realmente ayudarían.

Gracias por su tiempo y sus respuestas.

p.s. ¿Puedo usar solo un puerto para todos los clientes?

EDIT: Para aclarar, quiero codificar un servidor de eventos, pero no sé cómo hacerlo, así que acabo de hacer un ejemplo de lo que sé (encuestas de clientes).

Respuesta

0

Aquí hay un esqueleto del servidor para lo que pueda necesitar. No se manejan excepciones.

class Program 
{ 
    public static ManualResetEvent connected = new ManualResetEvent(false); 

    static void Main(string[] args) 
    { 
     string ip = "127.0.0.1"; 
     int port = 14500; 

     TcpListener server = new TcpListener(IPAddress.Parse(ip), port); 
     server.Start(); 

     Console.WriteLine("Server started..."); 

     while (true) 
     { 
      connected.Reset(); 
      server.BeginAcceptTcpClient(new AsyncCallback(AcceptCallback), server); 
      connected.WaitOne(); 
     } 
    } 

    public static void AcceptCallback(IAsyncResult ar) 
    { 
     TcpListener listener = (TcpListener)ar.AsyncState; 
     TcpClient client = listener.EndAcceptTcpClient(ar); 

     byte[] buffer = new byte[1024]; 
     NetworkStream ns = client.GetStream(); 
     if (ns.CanRead) 
     { 
      ns.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(ReadCallback), new object[] { ns, buffer }); 
     } 

     connected.Set(); 
    } 

    public static void ReadCallback(IAsyncResult ar) 
    { 
     NetworkStream ns = (NetworkStream)((ar.AsyncState as object[])[0]); 
     byte[] buffer = (byte[])((ar.AsyncState as object[])[1]); 
     int n = ns.EndRead(ar); 
     if (n > 0) 
     { 
      Console.WriteLine(Encoding.ASCII.GetString(buffer, 0, n)); 
     } 
     ns.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(ReadCallback), new object[] { ns, buffer }); 
    } 
} 
+0

Ejemplo horrible. No maneja excepciones o desconexiones del extremo remoto (lectura de 0 bytes). Convierte una aceptación asíncrona para sincronizar con un evento, ¿por qué no usar simplemente 'AcceptTcpClient'. No utilice contextos mágicos para realizar operaciones asincrónicas (en su caso una matriz de objetos); – jgauffin

1

No sé acerca de los marcos C#, pero puede echar un vistazo a Twisted, un marco de Python basado en eventos. Puede encontrar ejemplos de códigos de servidores y clientes, similares a sus necesidades.

Este es un ejemplo de un servidor muy simple que se hace eco de nuevo a cliente sea lo que recibió de ella:

#!/usr/bin/env python 

# Copyright (c) 2001-2009 Twisted Matrix Laboratories. 
# See LICENSE for details. 

from twisted.internet.protocol import Protocol, Factory 
from twisted.internet import reactor 

### Protocol Implementation 

# This is just about the simplest possible protocol 
class Echo(Protocol): 
    def dataReceived(self, data): 
     """ 
     As soon as any data is received, write it back. 
     """ 
     self.transport.write(data) 


def main(): 
    f = Factory() 
    f.protocol = Echo 
    reactor.listenTCP(8000, f) 
    reactor.run() 

if __name__ == '__main__': 
    main() 

En cuanto a la última pregunta: ¿

P. S. ¿Puedo usar solo un puerto para todos los clientes?

Sí, puede (cualquiera que sea el idioma/marco que utilice).

+0

+1 Se ve realmente interesante. Voy a tratar de crear la versión de .Net solo por diversión (cuando tengo el tiempo;)) – jgauffin

+0

@jgauffin ¿Lo portaste al final? – beppe9000

+0

@ beppe9000: http://blog.gauffin.org/2012/05/04/griffin-networking-a-somewhat-performant-networking-library-for-net/. La versión 2 está en griffin framework: http://blog.gauffin.org/2014/05/30/griffin-framework-performant-networking-in-net/ – jgauffin

1

Sugeriría utilizar WCF alojado como un servicio de Windows, que proporciona una plataforma escalable y multihilo. También se puede adaptar según los requisitos del protocolo.Este es un ejemplo que se puede utilizar como referencia:

http://msdn.microsoft.com/en-us/library/ms733069.aspx

+0

WCF lo hace terriblemente complicado, avaloid si U tiene una opción. Mucho más fácil hacerlo con tcplistener y async – Tom

1

Evento impulsado exactamente no describen lo que se espera que su sistema funciona así porque usted describe sondeo sus clientes los datos de proceso en lugar de sus clientes empujando sus datos a su servicio (desencadenando un evento).

Si tiene muy poca idea sobre cómo codificar un sistema como este, puede buscar soluciones/productos existentes para su escenario.

Recomiendo consultar herramientas de EAI como BlueIntegrator o BizTalk para integrar clientes POS.

Para su requisito referente al despliegue de actualizaciones de clientes, puede consultar BITS.

3

En primer lugar, si usted es nuevo en C# y multihilo y tomas de corriente, que es un montónde morder para su primer proyecto. Recomiendo aprender estos individualmente.

Dicho esto, usted puede encontrar Nito.Async.Sockets útil; incluye un socket de servidor controlado por eventos y maneja las preocupaciones de subprocesamiento múltiple por usted.

0

Llego un poco tarde a la fiesta, pero recientemente comencé un nuevo trabajo en el desarrollo de software para integrarme con instrumentos científicos y actualmente estoy pasando por el dolor de aprender a enhebrar, comunicaciones, procesamiento asíncrono, etc. ' He encontrado que el Threading in C# de Joe Albahari es un excelente recurso para aprender sobre el lado de las cosas.

Cuestiones relacionadas