2012-07-22 5 views
3

usocket FAQ은 내가 이것을해야하는 방법은 socket-stream을 읽고 end-of-file 결과를 확인하는 것입니다. 그것은 하나의 스레드가 소켓 당 활성 상태 인 경우에 작동하지만 동일한 스레드에서 여러 소켓을 처리하려고하는 경우에는 만족스럽지 않습니다.다른 쪽 끝이 단일 스레드에서 소켓 스트림을 닫았는지 어떻게 확인합니까?

내가 거기에 실제로 연결하는 네 개의 클라이언트를 가지고 있다고 가정이 연습

(defparameter *socket* (socket-listen "127.0.0.1" 123456)) 
(defparameter *client-connections* 
    (list (socket-accept *socket*) 
     (socket-accept *socket*) 
     (socket-accept *socket*) 
     (socket-accept *socket*))) 

같은 것을 생각해 보자. 연결이 끊긴 소켓이 여전히 listen-nil 반환하고, 활성 소켓에서 read을 시도하기 때문에 그것은 하나 개의 스레드에서 그들을 제공에 대해 이동하는 방법처럼 보인다는,이 작동하지 않습니다 제외

(wait-for-input *client-connections*) 
(loop for sock in *client-connections* 
     for stream = (socket-stream sock) 
     when (listen stream) 
     do (let ((line (read-line stream nil :eof))) 
       (if (eq line :eof) 
        (progn (delete sock *client-connections*) 
         (socket-close sock)) 
        (handle sock line)))) 

같은 것입니다 메시지가없는 메시지가있는 경우 다른 메시지가 준비되어 있지 않은 경우에도 메시지가없는 소켓이있는 경우에도 은 차단되지만wait-for-intput은 즉시 반환됩니다.

클라이언트가 잠시 동안 말을하지 않고 세 번째 클라이언트의 연결이 끊어진 상황에서는 특정 소켓 연결을 찾아서 닫는 좋은 방법이 아닌 것 같습니다. 나는 입력을 전혀하지 않고 read 블록 이후로 처음 두 클라이언트가 메시지를 보낼 때까지 스레드를 기다리게하는 것을 제외하고는 순서대로 읽어야합니다.

내가 마음에있어,하지만 어떤 결정 인터넷 검색 후 발견되지 않은 솔루션은, (우선 순위를 내림차순으로)입니다 : 읽기 경우 t을 반환 listen에, 그렇지 않으면 해당

  1. 함수는 대상의 스트림에서 end-of-file 마커를 반환합니다. (위의 listen을이 개념적 함수로 바꾸면 나머지는 그대로 쓰게됩니다)
  2. 그렇지 않으면 여행을 유발하는 닫힌 소켓 목록을 반환하는 함수가 wait-for-input과 같습니다.
  3. 을 반환 wait-for-input에, 그렇지 않으면 해당하는 함수 (필요에 따라이 경우, 내가 그들을 팝업/그들이 실제로 제안 read 기술로 폐쇄하고, 가까이있는 것을 확인, 폐쇄 소켓의 목록을 반복 수) 첫 번째 닫힌 소켓으로 인해 트립이 발생했습니다. (# 2와 같지만 속도가 느립니다. 반복 당 하나의 비활성 연결을 잘라 내기 때문에)
  4. 각 소켓 연결에서 입력을받은 시간을 추적하고 특정 시간이 지나도 관계없이 종료합니다 활동하지 않는 기간. (이 잠재적으로 주위를 더 이상 필요가 죽은 연결의 무리를 유지하는 것과 아마 어쨌든 할 싶어하지만, 일을 )
  5. 즉시 타임 아웃 스트림에서 read-char을 시도하는 함수, :eof을 만날 경우 t을 반환하고 다른 시간은 unread-char이됩니다 (시간 초과 또는 읽지 않음 후 nil을 반환). (명백하지 않은 치명적인 방식으로 쉽게 깨는 것처럼 보이기 때문에 최후의 수단이됩니다).

또한 정확히 내가 잘못 생각한 경우 그 점도 지적하십시오.

+0

당신은 그 소켓에서'select' 이벤트 루프를 에뮬레이트하려고합니까? –

+0

@VsevolodDyomkin - 예, 나는 "select"이벤트 루프가 무엇인지 완전히 모르겠지만 이벤트 루프를 만들려고합니다. – Inaimathi

답변

3

위의 옵션 2로 언급 한 것이 있음이 드러납니다. 메모리 관리를 위해 추적 연결의 전체 목록을 반환에

wait-for-input 기본값 (사람이 소문에 cons는 결과를 새 목록을 보내고에 대해 우려했다)하지만, 그것은 단지가 연결을 반환하도록 알려주는 &key 매개 변수가 있습니다 말할 것이 있습니다.

(wait-for-input (list conn1 conn2 conn3 conn4) :ready-only t) 

내가 찾고있는 곳입니다. 이것은 신호를 보내려는 것뿐만 아니라 모든 준비된 연결을 반환합니다. 따라서 루프는 여전히 두 경우를 처리해야합니다. 예 :

(loop for sock in (wait-for-input *client-connections* :ready-only t) 
     for stream = (socket-stream sock) 
     do (let ((line (read-line stream nil :eof))) 
      (if (eq line :eof) 
       (progn (delete sock *client-connections*) 
         (socket-close sock)) 
       (handle sock line)))) 

과 같이하면됩니다.