我对任何类型的插座几乎没有任何知识/经验,所以我的问题可能最终归咎于我的无知。
Guile没有任何协议的概念,但我认为,因为websockets只是HTTP请求,我应该能够至少使用Guile的Web模块发出请求。
我正在使用来自https://wsninja.io/#demo的wss://node2.wsninja.io来练习。
我写了
(let ([s (socket PF_INET SOCK_STREAM 0)]
[d (vector-ref (addrinfo:addr (car (getaddrinfo "echo.websocket.org" "https"))) 1)])
(connect s AF_INET d 443))
尝试连接。虽然getaddrinfo
要求一个协议(并且Guile不能识别"wss"
或"ws"
),但我只需要将IP地址作为一个整数,这就是它所做的一切 - 提取整数表示;结果与我在网上对其他一些服务进行验证的结果相符,所以看起来是正确的。
我使用PF_INET
和AF_INET
,因为如果我没有弄错的话,IPv4对于websocket调用是有意义的。我和SOCK_STREAM
一起去了,因为一旦打开,websocket会来回传输数据。
我将以上示例基于Guile在此提供的客户端示例:https://www.gnu.org/software/guile/manual/html_node/Internet-Socket-Examples.html#Internet-Socket-Examples。
我怀疑这是我错误的下一部分,但我不确定如何。
我认为,连接后,下一步是启动握手。鉴于Guile的例子,似乎可以通过显示到现在(理论上)打开的端口来完成,所以我这样做了:
(let ([s (socket PF_INET SOCK_STREAM 0)]
[d (vector-ref (addrinfo:addr (car (getaddrinfo "echo.websocket.org" "https"))) 1)])
(connect s AF_INET d 443)
(display "GET / HTTP/1.1\r\n" s)
(display "Host: localhost\r\n" s)
(display "User-Agent: Mozilla/5.0\r\n" s)
(display "Upgrade: websocket\r\n" s)
(display "\r\n" s)
(do ([line (read-line s) (read-line s)])
((eof-object? line))
(display line)
(newline)))
我也尝试过将握手作为一个String发送。直接从Guile示例中提取do
循环。
虽然我已经看到提到握手应该作为Websockets的标头发送,但我认为它与HTTP并不完全不同,Guile示例通过display
发送,但也许这是一个来源我的错误。
毋庸置疑,这不起作用。没有任何内容被display
编辑,并立即退出循环。但似乎我正在建立连接,因为将display
移到套接字导致它只是挂起(我假设是一个无休止的循环,因为没有eof-object
被发送,因为套接字正在等待握手)。
但如果我确实发送了一些东西,我就不会发出任何肯定甚至错误。所以我很困惑,有点超出我的深度,以为我会问。