4

HTTP 1.1 から WebSockets に切り替えて、プロトコルをアップグレードしようとしています。usocketを使用しようとしました。これまでのコードは次のとおりです ( GitHub gistとして入手できます)。ハンドシェイクの読み取り後、関数はリターンNILまたはunexpected EOFエラーになります。

;; Define parameter sock for usocket stream
;; echo.websocket.org is a site for testing websockets
(defparameter sock (usocket:socket-connect "echo.websocket.org" 80))

;; Output confirms WebSocket protocol handshake as this implemented in browsers 
(format (usocket:socket-stream sock) "~A~%~A~%~A~%~A~%~A~A~%~A~%~A~%~%" 
        "GET /?encoding=text HTTP/1.1"
        "Connection: Upgrade"
        "Host: echo.websocket.org"
        "Origin: http://www.websocket.org"
        "Sec-WebSocket-Key: " (generate-websocket-key)
        "Sec-WebSocket-Version: 13"
        "Upgrade: websocket")

;; Write output to stream
(force-output (usocket:socket-stream sock))

;; Returns NIL
(do ((line                                                             
      (read-line (usocket:socket-stream sock) nil)                        
      (read-line (usocket:socket-stream sock) nil)))                      
    ((not line))                                                       
  (format t "~A" line))

;; Returns error: unexpected EOF
(read-line (usocket:socket-stream sock))

;; Returns NIL
(listen (usocket:socket-stream sock))
4

1 に答える 1

9

~%FORMATステートメントでは、HTTP プロトコルの目的で移植することはできません。改行文字を出力します#\newline。改行は、コードが実行されるプラットフォームによって異なります: cr (古い Mac、Lisp マシン)、crlf (Windows)、または lf (Unix)。したがって、改行文字をストリームに書き込むと、出力は実行しているプラ​​ットフォーム (または Lisp システムが何をすべきと考えるか) に依存します。Windows には、HTTP と同じ行末規則があります。

ノート:

  • Unix システムでは、通常#\newlineは と同じ#\linefeedです。単一の文字。
  • Windows システムで#\newlineは、多くの場合、シーケンスと同じ#\return #\linefeedです。2 つの文字。Lisp システムによっては、これを無視して Unix の規則を使用する場合があります。

HTTP は crlf を使用します。crlf を確実に記述するには、文字#\return#\linefeed:を記述する必要があります(format stream "~a~a" #\return #\linefeed)

(defun write-crlf (stream)
  (write-char #\return stream)
  (write-char #\linefeed stream))

ただし、一部のサーバーは、標準の HTTP crlf 規則に従わない入力を読み取るほど愚かな場合があります。

ストリームを開くときに行末規則を指定する方法があるかもしれません。usocketただし、そのような機能は提供しません。

また、(完了を待機する) を使用し、( IO 操作の完了を待機しfinish-outputない) を使用しません。force-output

于 2014-09-01T17:53:46.477 に答える