简体   繁体   English

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

[英]Spawning multiple processes to handle many socket based connections in Clozure Common Lisp

I have the following: 我有以下几点:

(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)))))

When a connection comes in, it is accepted and a stream is passed to the handler. 当一个连接进入时,它被接受并且流被传递到处理程序。 The process waits (blocks) on the handler. 进程在处理程序上等待(阻止)。 So the next connection is processed when handler returns. 因此,当处理程序返回时,将处理下一个连接。

The workaround is to have one process(/thread) per connection, so a new connection doesn't have to wait for the handler to finish processing on the earlier connection. 解决方法是每个连接具有一个进程(/线程),因此新连接不必等待处理程序完成对较早连接的处理。

I tried by doing: 我尝试这样做:

(PROCESS-RUN-FUNCTION (gensym) 
  (lambda () (funcall handler stream)))

in place of just (funcall handler stream) , but this ends up erroring out, because the stream is not available by the time the handler gets called. 代替just (funcall handler stream) ,但这最终会(funcall handler stream) ,因为在调用处理程序时该流不可用。 Obviously because with-open-stream has exited by that time, and stream is out of scope and thus (maybe?) GC'd. 显然是因为那时with-open-stream已经退出,并且流超出了范围,因此(也许?)进行了GC。

Then I tried: 然后我尝试了:

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

instead of just (loop (handle-connection)) , which runs away spawning new processes at the speed of loop, because the waiting on socket part, doesn't block the execution anymore. 而不是(loop (handle-connection)) ,它以循环的速度运行,从而产生了新的进程,因为等待套接字的部分不再阻塞执行。

What is the right way to create separate threads/processes to handle many connections on the same socket? 创建单独的线程/进程以处理同一套接字上的许多连接的正确方法是什么?

You should not work with a stream, while you are concurrently closing it. 同时关闭流时,不要使用流。

You also should not use variables in the process, which get values from the outside of the process. 您也不应在流程中使用变量,这些变量会从流程外部获取值。 Pass all data you need to the function, which is running as a process, via arguments. 通过参数将所需的所有数据传递给作为流程运行的函数。

(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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM