2011-02-08 13 views
15

He escrito una serie de sistemas de red y tengo una buena idea de cómo funciona la red. Sin embargo, siempre termino teniendo una función de recepción de paquetes que es una declaración de cambio gigante. Esto está empezando a llegar a mí. Prefiero una forma elegante y orientada a objetos para manejar los paquetes recibidos, pero cada vez que trato de encontrar una buena solución siempre termino corto.Redes orientadas a objetos

Por ejemplo, digamos que tiene un servidor de red. Simplemente está esperando respuestas. Un paquete entra y el servidor necesita validar el paquete y luego necesita decidir cómo manejarlo.

Por el momento he estado haciendo esto al activar el ID del paquete en el encabezado y luego tener un enorme grupo de llamadas a funciones que manejan cada tipo de paquete. Con los complicados sistemas de red esto da como resultado una declaración de cambio monolítico y realmente no me gusta manejarlo de esta manera. Una forma que he considerado es utilizar un mapa de clases de controladores. Luego puedo pasar el paquete a la clase relevante y manejar los datos entrantes. El problema que tengo con esto es que necesito alguna forma de "registrar" cada manejador de paquetes con el mapa. Esto significa, generalmente, que necesito crear una copia estática de la clase y luego en el constructor registrarlo con el controlador central de paquetes. Mientras esto funciona, realmente parece una manera poco elegante e incómoda de manejarlo.

Editar: Igualmente sería ideal tener un buen sistema que funcione en ambos sentidos. es decir, una estructura de clases que maneja fácilmente el envío de los mismos tipos de paquetes que los reciben (obviamente a través de diferentes funciones).

¿Alguien puede indicarme una mejor manera de manejar los paquetes entrantes? Enlaces e información útil son muy apreciados!

Disculpas si no he descrito bien mi problema ya que mi incapacidad para describirlo también es la razón por la que nunca he logrado encontrar una solución.

+0

No necesita una copia estática de las clases de controlador. Puede pasar instancias en el constructor. Sin embargo, no hay una gran mejora. :( –

+0

@Martinho: Pero eso significa que en algún lugar tengo que crear una instancia de cada clase posible. Cuando, como en el archivo de implementación de la clase, declaro una versión estática de sí mismo, el constructor recibe automáticamente una llamada. – Goz

+0

¿Has visto http? : //ieeexplore.ieee.org/xpl/freeabs_all.jsp? arnumber = 631153? –

Respuesta

5

Acerca de la forma de manejar el tipo de paquete: para mí, el mapa es el mejor. Sin embargo, usaría una matriz simple (o un vector) en lugar de un mapa. Haría el tiempo de acceso constante si enumera sus tipos de paquetes secuencialmente de 0.

En cuanto a la estructura de la clase. Hay bibliotecas que ya hacen este trabajo: Available Game network protocol definition languages and code generation. P.ej. Google's Protocol Buffer parece ser prometedor. Genera una clase de almacenamiento con getters, setters, serialización y rutinas de deserialización para cada mensaje en la descripción del protocolo. El lenguaje de descripción de protocolo se ve más o menos rico.

1

Un mapa de instancias de controlador es prácticamente la mejor manera de manejarlo. Nada de poco elegante al respecto.

+1

pero sin duda sangrienta incómoda;). – Goz

+0

todavía no puede evitar pensar que hay una mejor manera de manejarlo, sin embargo ... – Goz

+1

Hay una cantidad fija de incómoda y en este caso solo se trata de cómo y dónde la extienden. – Blrfl

1

En mi experiencia, el análisis sintáctico basado en tablas es el método más eficiente.

Aunque std::map es bueno, termino usando tablas estáticas. El std::map no se puede inicializar estáticamente como una tabla constante. Debe estar cargado durante el tiempo de ejecución. Las tablas (matrices de estructuras) pueden declararse como datos e inicializarse en tiempo de compilación. No he encontrado mesas lo suficientemente grandes donde una búsqueda lineal sea un cuello de botella. Por lo general, el tamaño de la tabla es lo suficientemente pequeño como para que la sobrecarga en una búsqueda binaria sea más lenta que una búsqueda lineal.

Para un alto rendimiento, usaré los datos del mensaje como un índice en la tabla.

1

Cuando estás haciendo OOP, tratas de representar cada cosa como un objeto, ¿verdad? De modo que sus mensajes de protocolo también se convierten en objetos; probablemente tenga una clase base YourProtocolMessageBase que encapsulará el comportamiento de cualquier mensaje y de la cual heredará sus mensajes polimórficamente especializados. Luego, solo necesita una forma de convertir cada mensaje (es decir, cada instancia de YourProtocolMessageBase) en una cadena de bytes, y una forma de hacerlo al revés. Dichos métodos se denominan técnicas serialization; algunos implementations basados ​​en metaprogramación existen.

ejemplo

rápida en Python:

from socket import * 
sock = socket(AF_INET6, SOCK_STREAM) 
sock.bind(("localhost", 1234)) 
rsock, addr = sock.accept() 

bloques de servidor, el fuego de otra instancia para un cliente:

from socket import * 
clientsock = socket(AF_INET6, SOCK_STREAM) 
clientsock.connect(("localhost", 1234)) 

Ahora usa Python módulo incorporado serialización, pickle; cliente:

import pickle 
obj = {1: "test", 2: 138, 3: ("foo", "bar")} 
clientsock.send(pickle.dumps(obj)) 

Servidor:

>>> import pickle 
>>> r = pickle.loads(rsock.recv(1000)) 
>>> r 
{1: 'test', 2: 138, 3: ('foo', 'bar')} 

Por lo tanto, como se puede ver, me acaba de enviar un enlace local objeto de Python . ¿No es este POO?

Creo que la única alternativa posible a la serialización es mantener las clases ID de Bimap. Esto parece realmente inevitable.

1

Quiere seguir usando el mismo protocolo de red de paquetes, pero traduzca eso a un objeto en la programación, ¿verdad?

Existen varios protocolos que le permiten tratar los datos como objetos de programación, pero parece que no desea cambiar el protocolo, solo la forma en que se trata en su aplicación.

¿Los paquetes vienen con algo así como una "etiqueta" o metadatos o cualquier "id" o "tipo de datos" que le permite asignar a una clase de objeto específico? Si lo hace, puede crear una matriz que almacena la identificación. y la clase correspondiente, y generar un objeto.

+0

Sí, sí tiene una identificación de paquete. No veo cómo identificaría los tipos de paquetes sin alguna forma de identificación única ... – Goz

+0

Si nos puede la identificación del paquete. para "clasificar un paquete", entonces puede hacer algo como: función de objeto PacketToClass (string packetTypeTag) {...} una función que genera un objeto de una clase dada en función de un id., también llamado patrón de "fábrica", o suave de – umlcat

1

Una forma más de OO para manejar esto es construir una máquina de estado usando el patrón de estado.

Manejo de datos en bruto entrante está analizando en máquinas de estado proporcionan una solución elegante (que tendrá que elegir entre el elegante y rendimiento)

Usted tiene un búfer de datos a procesar, cada estado tiene un método búfer mango que se analiza y procesa su parte del búfer (si ya es posible) y establece el siguiente estado en función del contenido.

Si desea obtener rendimiento, aún puede usar una máquina de estado, pero omita la parte de OO.

Cuestiones relacionadas