Сетевые подключения Emacs Lisp - что делать с объектом процесса? - PullRequest
6 голосов
/ 05 июня 2011

Предположим, что на локальном хосте запущен и работает TCP-сервер: 8080, на другом диалекте Лиспа, который понимает списки. Теперь я открываю сетевое соединение в Elisp

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

и успешно назначить открытый объект сетевого процесса переменной pserv. Но что дальше, как я могу использовать этот объект процесса для отправки запросов на сервер? Что я хочу сделать, это отправить списки на другой сервер (код в виде данных), которые оцениваются и результаты возвращаются.

В приведенном выше утверждении "test1.l" - это буфер Emacs, связанный с процессом, поэтому результаты должны быть напечатаны в этом буфере. Что если я добавлю nil и процесс не будет связан ни с каким буфером - как мне получить доступ к результатам сервера (возможно, также в виде списка) из Elisp или из объекта процесса?

Руководство Elisp, похоже, принимает эти знания как должное, но я немного растерялся здесь. Любые намеки будут оценены.

Ответы [ 2 ]

10 голосов
/ 05 июня 2011

Клиент-серверное взаимодействие осуществляется через асинхронные процессы.Это означает, что, к сожалению, у вас нет функции «отправить», которая передает данные для отправки на сервер и возвращает вам ответ сервера.Причина этого в том, что сетевое взаимодействие может быть медленным и блокировать все другие операции в Emacs, который является однопоточной программой.

Чтобы отправить данные на ваш сервер, используйте (process-send-string process string).Первый параметр - это ваше сетевое соединение, которое Emacs рассматривает как асинхронные процессы.Поскольку этот подпроцессный объект уже сохранен в переменной pserv, вы можете написать:

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

, чтобы отправить строку на сервер.

Чтобы прочитать ответ сервера, выиспользуйте функцию фильтра процесса , которая является обратным вызовом, который вызывается с тем, что сервер отправляет вам обратно.Поэтому сначала нужно определить такую ​​функцию обратного вызова, скажем:

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

Эта функция принимает два аргумента: сетевой процесс и данные контента, которые отправляет сервер.Однако есть один хитрый момент: ответ сервера может быть разбит на суб-содержимое.То есть, когда вызывается handle-server-reply, аргумент content может содержать только части ответа сервера.Это может быть вызвано снова позже с дальнейшим содержанием.Поэтому убедитесь, что вы обрабатываете это правильно.

Чтобы объявить вашу функцию в качестве обратного вызова, используйте:

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

Как всегда, кодировка символов может быть простой, поэтому посмотрите на следующие две функциии решить, могут ли они вам понадобиться:

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

Обязательно установите эти до назначения функции фильтра процесса.

Возможно, вам также будет интересно узнать состояниевашего сетевого соединения, например, для обработки случаев, когда соединение неожиданно закрывается.Для этого вы можете использовать так называемые сторожевые функции , еще один тип обратного вызова, через который вы получаете информацию об изменениях статуса процесса:

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

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

Параметр event содержит информациюо том, как изменился статус подключения.

Я думаю, что документация по процессу Emacs уже упоминалась ранее.Это определенно стоит прочитать.

4 голосов
/ 05 июня 2011

В Emacs сетевое соединение обрабатывается как асинхронный подпроцесс.Таким образом, здесь также применимы инструкции по отправке ввода или чтению вывода из подпроцессов.

Чтобы отправить что-либо на сервер, см. Ввод в процессы , а для чтения результатов см. Вывод из процессов .

Информация передается по сети в виде строки, поэтому вы можете захотеть использовать read или read-from-string после получения данных с сервера.См. Функции ввода .

...