在Clozure Common Lisp中生成多个进程来处理许多基于套接字的连接



我有以下内容:

(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),但这最终会出错,因为在调用处理程序时流不可用。很明显,因为当时开放流已经退出,并且流超出了范围,因此(可能?)GC’d。

然后我尝试了:

(loop 
(PROCESS-RUN-FUNCTION (gensym) 
(lambda () 
(format t "new process ") 
(handle-connection))))

而不仅仅是(loop (handle-connection)),它以循环的速度产生新的进程,因为套接字上的等待部分不再阻止执行。

创建单独的线程/进程以处理同一套接字上的多个连接的正确方法是什么

当您同时关闭流时,不应该处理它。

您也不应该在流程中使用从流程外部获取值的变量。通过参数将所需的所有数据传递给作为进程运行的函数。

(let ((accepted-stream (acception-connection socket      ; just take the stream
:wait t)))
(process-run-function               ; run a function as a process/thread
(gensym "CONNECTION-HANDLER-")    ; generate a name
(lambda (stream)                  ; take the one argument, the stream
(unwind-protect (progn ...)     ; do something, with clean-up
(close stream)))              ; make sure the stream gets closed
accepted-stream))                 ; pass the stream, which then gets passed to
; the lambda function

最新更新