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

标签 multithreading sockets concurrency common-lisp ccl

我有以下内容:

(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处理程序流),但这最终会出错,因为在调用处理程序时流不可用。显然,因为当时 with-open-stream 已经退出,并且 Stream 超出了范围,因此(也许?)GC。

然后我尝试了:

(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

关于multithreading - 在 Clozure Common Lisp 中生成多个进程来处理许多基于套接字的连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41651570/

相关文章:

c++ - 如何在多个接口(interface)上绑定(bind)到同一个 UDP 端口

javascript - 在 Socket.io 中设置 XMLHttpRequest 的 withCredentials 属性

由于 NSSQLiteErrorDomain = 1032,iOS 核心数据 saveContext 方法不成功

php - 一次运行多个 exec 命令(但要等待最后一个完成)

java - 如何强制我的线程按顺序运行?

c - 使用原始套接字从 recvfrom 获取数据

c++ - 是否有一个真正有效的示例显示 x86_64 上 Store-Load 重新排序的副作用?

Java:被过度调用的方法的设计模式

c++ - 如何在没有互斥实例的情况下正确编译 lock_guard<mutex> 构造函数?

python - 在python中记录多线程进程