Я пытаюсь написать клиент Ruby для веб-сокетов. Я могу подключиться через TCPSocket, завернутый в SSLSocket, отправить первоначальное рукопожатие и получить ожидаемый ответ (HTTP / 1.1 101 протокол переключения, с правильным ключом Sec-Websocket-Accept и т. Д.). Однако после отправки моего первого сообщения в рамке веб-сокета я не могу прочитать ответ. Обнаружение порта с помощью tcpdump означает, что сервер отправляет обратно хотя бы одно сообщение ненулевой длины:
after successful handshake, sending request here:
13:31:00.656516 IP nifty.54930 > streamer-ws-tx.tdameritrade.com.https: Flags [P.], seq 697:1259, ack 3256, win 316, length 562
...
13:31:00.679138 IP streamer-ws-tx.tdameritrade.com.https > nifty.54930: Flags [.], ack 1259, win 2483, length 0
...and getting back 33 bytes of response
13:31:00.679777 IP streamer-ws-tx.tdameritrade.com.https > nifty.54930: Flags [P.], seq 3256:3289, ack 1259, win 2483, length 33
13:31:00.720433 IP nifty.54930 > streamer-ws-tx.tdameritrade.com.https: Flags [.], ack 3289, win 316, length 0
13:31:18.504672 IP nifty.54930 > streamer-ws-tx.tdameritrade.com.https: Flags [F.], seq 1259, ack 3289, win 316, length 0
Я считаю, что сообщение, которое я отправляю после рукопожатия, хорошо отформатировано, потому что я тестировал отправку того же сообщения в консоли Chrome, и там я вижу ожидаемый ответ.
В отладчике ruby после отправки сообщения я могу прочитать 4 байта из сокета SSL-TCP с помощью read_non_block ():
"\ X88 \ x02 \ x03 \ X Е8"
или же
Ниже приведена выдержка из моего кода.
@handshake = WebSocket::Handshake::Client.new(
url: websocket_url,
port: 443,
)
server = TCPSocket.new(@handshake.host, @handshake.port)
ctx = OpenSSL::SSL::SSLContext.new
ctx.set_params(verify_mode: OpenSSL::SSL::VERIFY_PEER)
@socket = OpenSSL::SSL::SSLSocket.new(server, ctx).tap do |socket|
socket.sync_close = true
socket.connect
end
# send handshake
@socket.puts @handshake.to_s
while ! @handshake.finished?
s = @socket.gets
next unless s
puts s
@handshake << s
end
if !@handshake.valid?
print "Fail. Handshake invalid.\n"
exit(1)
end
frame = WebSocket::Frame::Outgoing::Client.new(
version: @handshake.version,
data: JSON.generate(request),
type: :text)
@socket.puts frame.to_s
frm_in = WebSocket::Frame::Incoming::Client.new(version: @handshake.version)
result = @socket.gets
Выполнение застревает в последней строке.
Как правильно читать из сокета SSL-TCP, подключенного к серверу веб-сокетов?
(у меня Ubuntu 18.04 и Ruby-2.6.0)