2011-06-04 13 views
6

Supongamos que hay un servidor TCP ejecutándose en localhost: 8080, en otro dialecto Lisp que comprende las listas. Ahora abro una conexión de red en ElispConexiones de red Emacs Lisp: ¿qué hacer con el objeto de proceso?

setq pserv (open-network-stream plisp "test1.l" "localhost" 8080) 

y asigno exitosamente un objeto de proceso de red abierto a la variable pserv. Pero luego, ¿cuál es el siguiente paso? ¿Cómo uso este objeto de proceso para enviar solicitudes al servidor? Lo que quiero hacer es enviar listas al otro servidor (código como datos) que se evalúan y se devuelven los resultados.

En la declaración anterior, "test1.l" es el búfer de Emacs asociado con el proceso, por lo que los resultados se deben imprimir en ese búfer. ¿Qué pasa si pongo nil allí y el proceso no está asociado con ningún búfer - ¿cómo puedo acceder a los resultados del servidor (posiblemente también en forma de lista) de Elisp o del objeto de proceso?

El manual de Elisp parece dar ese conocimiento por hecho, pero estoy un poco perdido aquí. Todos los consejos serían apreciados.

Respuesta

10

La comunicación entre el cliente y el servidor se realiza mediante procesos asíncronos. Eso significa que, lamentablemente, no tiene una función de "enviar" que pase sus datos para enviarlos al servidor y que le devuelva la respuesta del servidor. La razón de esto es que la comunicación de red puede ser lenta y eso bloquearía todas las demás operaciones dentro de Emacs, que es un programa de subproceso único.

Para enviar datos a su servidor, use (process-send-string process string). El primer parámetro es su conexión de red, que Emacs trata como procesos asincrónicos. Puesto que usted tiene que subproceso a objetos ya almacenado en la variable pserv, se podría escribir:

(process-send-string pserv "(my data (can be (in) (list) form))") 

para enviar una cadena al servidor.

Para leer la respuesta del servidor, utiliza un process filter function, que son devoluciones de llamada que se invocan con lo que el servidor le devuelva. Por lo que primero tiene que definir una función de devolución de llamada como, por ejemplo:

(defun handle-server-reply (process content) 
    "Gets invoked whenever the server sends data to the client." 
    ...) 

Esta función toma dos argumentos, el proceso de la red y los datos de contenido que el servidor envía. Sin embargo, hay un punto complicado: la respuesta del servidor puede dividirse en subtemas. Es decir, cuando se llama a handle-server-reply, el argumento content solo puede contener partes de la respuesta del servidor. Es posible que vuelva a llamar después con más contenido. Así que asegúrate de manejarlo correctamente.

Declarar su función como una devolución de llamada, utilice:

(set-process-filter pserv 'handle-server-reply) 

Como siempre, la codificación de caracteres puede ser una pita, así que busca en las dos funciones siguientes y decidir si se pueden necesitar:

(set-process-filter-multibyte pserv t) 
(set-process-coding-system pserv 'utf-8 'utf-8) 

Asegúrese de configurar estos antes de asignando una función de filtro de proceso.

También podría interesarle encuestar el estado de su conexión de red, por ejemplo, para manejar casos donde la conexión se cierra inesperadamente. Para que pueda utilizar los llamados sentinel functions, otro tipo de devolución de llamada a través del cual te informamos acerca de los cambios del estado del proceso:

(set-process-sentinel pserv 'sentinel-function) 

(defun sentinel-function (process event) 
    "Gets called when the status of the network connection changes." 
    ...) 

event El parámetro contiene la información sobre la forma en que ha cambiado el estado de la conexión.

Creo que se ha señalado anteriormente el Emacs process documentation. Definitivamente vale la pena leer.

+0

Gracias Thomas, ¡una respuesta muy detallada y útil! – Thorsten

+0

que está prácticamente copiado del manual. El manual es muy bueno. Deberías leerlo. –

+0

@nicferrier Estoy de acuerdo, es por eso que mi respuesta contiene múltiples enlaces al manual. – Thomas

4

En Emacs, una conexión de red se trata como un subproceso asíncrono. Por lo tanto, las instrucciones para enviar o leer datos desde subprocesos también se aplican aquí. Para enviar algo al servidor, vea Input to Processes, y para leer los resultados, vea Output from Processes.

La información se transmite a través de la red en forma de cadena, por lo que es posible que desee utilizar read o read-from-string después de recibir datos del servidor. Ver Input Functions.

+0

Su respuesta ya dio la información clave: tratar las conexiones de red como subprocesos asíncronos. Entonces puedo leer el manual de Elisp para más información ... Gracias. – Thorsten

Cuestiones relacionadas