【问题标题】:WebSocket handshake response missing HTTP status lineWebSocket 握手响应缺少 HTTP 状态行
【发布时间】:2020-06-28 08:14:48
【问题描述】:

由于对该主题感兴趣,我决定尝试使用 TCP 为 Kotlin 制作 WebSocket 客户端库。

所以,我正在阅读 RFC6455,它提到在握手中,服务器响应应该有一个 HTTP 状态行。酷,我提出我的要求:

GET / HTTP/1.1
Host: echo.websocket.org:80
Upgrade: websocket
Connection: Upgrade
Accept: */*
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: Dg8CY18ZTGbAkIzNhpO3mA==

服务器回复

Connection: Upgrade
Sec-WebSocket-Accept: akyZ/0pr8WyuXVfejRWVAUGSW3k=
Upgrade: websocket

如您所见,没有 HTTP 状态行。我是否遗漏了 RFC6455 中的某些内容,我的代码很笨吗?

代码(PayloadFactory.kt):

fun createSecWebSocketKey(): String? {
    val bytes = ByteArray(16)
    SecureRandom.getInstanceStrong().nextBytes(bytes)
    return String(Base64.getEncoder().encode(bytes)!!)
}

fun createOpeningHandshake(host: String, path: String = "/", port: Int = 80, protocolVersion: Int = 13): String
{
    // I'm aware path isn't used yet, that's something I plan to implement but haven't yet.
    var handshake = ""
    handshake += "GET / HTTP/1.1\r\n"
    handshake += "Host: $host:$port\r\n"
    handshake += "Upgrade: websocket\r\n"
    handshake += "Connection: Upgrade\r\n"
    handshake += "Accept: */*\r\n"
    handshake += "Sec-WebSocket-Version: $protocolVersion\r\n"
    handshake += "Sec-WebSocket-Key: ${createSecWebSocketKey()}\r\n\r\n"
    return handshake
}

代码(WebSocket.kt):

class WebSocket(protocol: String, host: String, port: Int = 80, protocolVersion: Int = 13) {
    private val client: Socket = Socket(host, port)
    private val globallyUniqueIdentifier = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"

    init {
        val handshake = createOpeningHandshake(host, protocolVersion = protocolVersion)
        println("============CLIENT HANDSHAKE============")
        println(handshake)
        client.getOutputStream().write(handshake.toByteArray())
        println("============SERVER RESPONSE=============")
        val input = BufferedReader(InputStreamReader(client.getInputStream()))
        while (true)
        {
            if (input.readLine() != null) {
                val line = input.readLine()
                println(line)
            }
        }
    }
}

运行: WebSocket("ws", "echo.websocket.org", 80)

【问题讨论】:

  • 您正在丢弃响应的每一行奇数。您需要将第一个readLine() 的结果存储到一个变量中,测试它是否为空,如果不是,则显示它。并且不执行第二个readLine()。如果它为空,则需要退出读取循环。
  • user207421 你太棒了,我自己应该看到的,但是非常感谢你指出并解决了我的问题!
  • 一点也不惊艳,只是有经验。通常的写法是while ((line = input.readLine()) != null) {...}
  • 谢谢,我只是个白痴。我从 9 岁就开始编码,现在我 17 岁,我应该看到这个错误。太感谢了!并感谢编写循环的更有效方式,我很感激!
  • (小提示:我们不会在此处的主题行中使用 [已解决] 设备 - 请点击您答案上的勾号/复选标记。我们倾向于不鼓励在帖子中提供投票建议/评论 - 我们不要认为它有任何作用,否则它可能会鼓励人们投反对票。反正对大多数读者来说它没有用。如果你愿意,把它放在 cmets 中)。

标签: kotlin websocket tcp rfc6455


【解决方案1】:

已解决

我没有将 readLine() 的结果存储在变量中,导致我基本上丢弃了响应中的每一行奇数行。感谢 user207421 指出!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-18
    • 2018-09-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    相关资源
    最近更新 更多