Двунаправленный сокет в списке - PullRequest
0 голосов
/ 10 сентября 2018

Я пытаюсь установить связь из сценария Lisp с другой программой, используя сокеты TCP / IP (с sbcl и библиотекой usocket в системе Linux).

Пока я получил этот код:

(require 'asdf)
(require 'usocket)

(defun start-client ()
    (   usocket:with-client-socket
    (socket stream "0.0.0.0" 30000)


    (loop for x in '("1~%" "2~%" "3~%" "4~%" "5~%") do 
        (format stream x)
        (force-output stream)
        (sleep 1)
        ;;(format t "~A~%" (read-line stream))
    )
    )
)
(start-client)

Код работает хорошо, за исключением закомментированной строки:

(format t "~A~%" (read-line stream))

Таким образом, я могу отправлять и получать сообщения 1,2,3 ... из другого сокета (другой программы) и отправлять сообщения обратно из другой программы на lisp. Однако когда я раскомментирую строку для чтения сообщений из lisp, приведенный выше код, кажется, останавливается и ждет вечно.

1 Ответ

0 голосов
/ 11 сентября 2018

Трудно сказать, в чем ваша проблема, не зная сервера. Может быть, это никогда не завершает линию?

Вот небольшая демонстрация, использующая потоки для изоляции клиента и сервера:

(in-package #:cl-user)

(eval-when (:compile-toplevel :load-toplevel :execute)
  (ql:quickload '("usocket" "bordeaux-threads")))

(defpackage #:usocket-demo
  (:use #:cl))

(in-package #:usocket-demo)

(defun serve (port)
  "Starts a socket server to answer a single request."
  (usocket:with-socket-listener (server-socket "0.0.0.0" port
                                               :reuse-address t)
    (let* ((stream-socket (usocket:socket-accept server-socket))
           (server-stream (usocket:socket-stream stream-socket))
           (request (read-line server-stream)))           ; read
      (format t "S> serving…~%")
      (format server-stream "Hello, ~a!~%" request)       ; write
      (finish-output server-stream))))

(defun cly (port)
  "Makes a single request to a server and prints the answer."
  (usocket:with-client-socket (client-socket client-stream "0.0.0.0" port)
    (format client-stream "Issa me!~%")                   ; write
    (finish-output client-stream)
    (let ((response (read-line client-stream)))           ; read
      (format t "C> I got a response: ~a~%" response))))

(defun run-demo ()
  (let ((bt:*default-special-bindings*
          `((*standard-output* . ,*standard-output*))))
    (bt:make-thread (lambda ()
                      (serve 13575))
                    :name "Server")
    (bt:make-thread (lambda ()
                      (cly 13575))
                    :name "Client")
    (values)))

Привязка bt:*default-special-bindings необходима для того, чтобы потоки видели один и тот же поток вывода для демонстрационных сообщений.

Как видите, и клиент, и сервер имеют поток, из которого они могут читать и записывать.

...