У меня есть следующее:
(defun serve (&key (port 80) (handler #'IDENTITY))
(WITH-OPEN-SOCKET
(socket :LOCAL-PORT port
:LOCAL-HOST "localhost"
:CONNECT :PASSIVE
:REUSE-ADDRESS t)
(flet ((handle-connection ()
(with-open-stream
(stream (ACCEPT-CONNECTION socket :wait t))
(funcall handler stream))))
(loop (handle-connection)))))
Когда приходит соединение, оно принимается, и поток передается обработчику. Процесс ожидает (блокирует) обработчик. Таким образом, следующее соединение обрабатывается, когда обработчик возвращается.
Обходной путь состоит в том, чтобы иметь один процесс (/поток) для каждого соединения, поэтому новому соединению не нужно ждать, пока обработчик завершит обработку предыдущего соединения.
Я попытался сделать:
(PROCESS-RUN-FUNCTION (gensym)
(lambda () (funcall handler stream)))
вместо просто (funcall handler stream)
, но это заканчивается ошибкой, потому что поток недоступен к моменту вызова обработчика. Очевидно, потому что with-open-stream к тому времени вышел, а поток выходит за рамки и, следовательно, (может быть?) GC.
Затем я попробовал:
(loop
(PROCESS-RUN-FUNCTION (gensym)
(lambda ()
(format t "new process ")
(handle-connection))))
вместо просто (loop (handle-connection))
, который убегает, порождая новые процессы со скоростью цикла, потому что ожидание в части сокета больше не блокирует выполнение.
Как правильно создать отдельные потоки/процессы для обработки множества подключений к одному сокету?