Продолжаю щупать скобочки, решил попробовать Common Lisp. Написал простенький tcp сервер, сделал на сокетах (usocket). Выглядит страшненько, но не знаю как написать «правильнее», поэтому решил поинтересоваться у гуру:
(defun create-server (port)
(let ((socket (usocket:socket-listen "127.0.0.1" port :reuse-address t)))
(unwind-protect
(loop
(let ((connection (usocket:socket-accept socket :element-type 'character)))
(progn
(usocket:wait-for-input connection :timeout 10)
(let ((input-data (read-line (usocket:socket-stream connection))))
(when (eq input-data nil) (return))
(format t "Server input is: ~a~%" input-data))
(format (usocket:socket-stream connection) "Pong~%")
(force-output (usocket:socket-stream connection))
(usocket:socket-close connection))))
(progn
(format t "Closing socket.~%")
(usocket:socket-close socket)))))
Первое, что мне кажется не очень правильным это три вложенных let. Вроде поправил на:
(defun create-server (port)
(let ((socket (usocket:socket-listen "127.0.0.1" port :reuse-address t)))
(unwind-protect
(loop
(let* ((connection (usocket:socket-accept socket :element-type 'character))
(stream (usocket:socket-stream connection))
(input-data (read-line stream nil)))
(progn
(usocket:wait-for-input connection :timeout 10)
(when (eq input-data :eof) (return))
(format t "Server input is: ~a~%" input-data)
(format stream "Pong~%")
(force-output stream)
(usocket:socket-close connection))))
(progn
(format t "Closing socket.~%")
(usocket:socket-close socket)))))
Но теперь задержка между отправкой с клиента «Ping» и получением «Pong» стала заметна, возможно проблема в том, что я делаю что-то неправильное с stream
и читаю/пишу туда раньше времени. Код клиента
(defun create-client (port)
(let* ((socket (usocket:socket-connect "127.0.0.1" port)))
(unwind-protect
(progn
(format (usocket:socket-stream socket) "Ping~%")
(force-output (usocket:socket-stream socket))
(usocket:wait-for-input socket :timeout 10)
(format t "Input is: ~a~%" (read-line (usocket:socket-stream socket))))
(usocket:socket-close socket))))
Во-вторых, сервер не отрабатывает условие отключения со стороны клиента (пока хочу сделать, чтобы сервер завершал свою работу при отключении клиента). В документации написано:
Reading from a stream which has been closed at the remote end signals an END-OF-FILE condition, meaning that reading from the stream and detecting that condition is the way to do it.
Понимаю только то, что проблема, где-то тут: (when (eq input-data :eof) (return))
– или опять же таки где в моей работе со стримами.
Почему не использую usocket:socket-server
? Отвечаю: я так понял, что туда нельзя передать сокет, чтобы ответить что-то клиенту, а же хочу не только читать что мне прислали.
Помогите маленькому лисперу понять что не так. Знаю, что monk хорошо разбирается в лиспах, из недавнего треда выяснил, что lovesan в них тоже много понимает и den73 тоже.