Day03 - 连接Ptt WebSocket

PTT自2017年6月开始实验性开放WebSocket,到2020年1月1日已公告正式支援,现今以WebSocket登入PTT已经成为主要的连线方式之一,由於我以前也没用过,正好趁这次的机会尝试看看。

在连线上我使用的是TooTallNateJava-WebSocket

dependencies {
    implementation "org.java-websocket:Java-WebSocket:1.5.1"
}

然後网路权限不能忘记,我自己在做新专案的时候真的蛮常忘记这个的Orz。

<uses-permission android:name="android.permission.INTERNET" />

使用上需要继承org.java_websocket.client.WebSocketClient,里面会包含Server的callback内容。

import android.util.Log
import org.java_websocket.client.WebSocketClient
import org.java_websocket.drafts.Draft_6455
import org.java_websocket.handshake.ServerHandshake
import java.net.URI
import java.nio.ByteBuffer

class WebSocketTest(serverUri: URI, header: MutableMap<String, String>) :
    WebSocketClient(serverUri, Draft_6455(), header) {

    private val tag = "WebSocketTest"

    override fun onOpen(handshakedata: ServerHandshake?) {
        Log.d(tag, "onOpen: ")
    }

    override fun onMessage(message: String?) {
        Log.d(tag, "onMessage: $message")
    }

    override fun onMessage(bytes: ByteBuffer?) {
        super.onMessage(bytes)
        Log.d(tag, "onMessage: ${bytes?.array()?.size}")
    }

    override fun onClose(code: Int, reason: String?, remote: Boolean) {
        Log.d(tag, "onClose: code=$code, reason=$reason, remote=$remote")
    }

    override fun onError(ex: Exception?) {
        Log.d(tag, "onError: $ex")
    }
}

接着直接尝试看看:

val hashMap = mutableMapOf<String, String>()
hashMap["origin"] = "https://term.ptt.cc"
val client = WebSocketTest(URI.create("wss://ws.ptt.cc:443/bbs"), hashMap)

client.connectBlocking(30,TimeUnit.SECONDS)

成功连线的话会看到以下log

D/WebSocketTest: onOpen:
D/WebSocketTest: onMessage: 1024
D/WebSocketTest: onMessage: 1024
D/WebSocketTest: onMessage: 190

可以看到Ptt Server是直接回传ByteBuffer,也就是我们在连线时看到的画面内容,接下来就是需要对这些Byte Array做解析。
另外在连线时需加上header origin,若没加的话会连线失败,Log如下:

D/WebSocketTest: onClose: code=1002, reason=Invalid status code received: 403 Status line: HTTP/1.1 403 Forbidden, remote=false

稍微Google了一下看起来这是WebSocket协定中定义的栏位,总之是必须的。

Origin header
The WebSocket standard defines an Origin header field, which web browsers set to the URL that originates a WebSocket request. This can be used to differentiate between WebSocket connections from different hosts, or between those made from a browser and some other kind of network client. However, remember that the Origin header is essentially advisory: non-browser clients can easily set the Origin header to any value, and thus “pretend” to be a browser.

You can think of the Origin header as roughly analogous to the X-Requested-With header used by AJAX requests. Web browsers send a header of X-Requested-With: XMLHttpRequest, which can be used to distinguish between AJAX requests made by a browser and those made directly. However, this header is easily set by non-browser clients, and thus isn’t trusted as a source of authentication.

In the same way, you can use the Origin header as an advisory mechanism—one that helps differentiate WebSocket requests from different locations and hosts, but you shouldn’t rely on it as a source of authentication.

上述来源

下一篇预计会是Parsing的部分了。不过正好进入中秋连假,希望我能撑住吧...


<<:  虹语岚访仲夏夜-4(专业的小四篇)

>>:  缺乏计画的目标,只能叫做愿望。----目标设定篇(上)

DAY17-MERN

前言: 在大致介绍完React的特性後,我们要延伸聊聊用React写网页时,最好用的前後端架构,M...

Day 14 网页分析 - Web Application Analysis (wpscan - WordPress vulnerability scanner)

前言 又进到一个新的分类Web Application Analysis,顾名思义就知道要来分析网站...

[Day25]DDL语句建立资料表2

建立资料表:CREATE TABLE 说明: 建立资料表之前,首先必须拥有DBA授权的CREATE ...

【Day 3】机器学习基本功(一)

机器学习三大步骤 定义一个模型(model) 从模型里挑出好的函式(function) 经由演算法找...