Socket
必要相依性:io.ktor:ktor-network, io.ktor:ktor-network-tls
程式碼範例: sockets-server, sockets-client, sockets-client-tls
除了伺服器與用戶端的 HTTP/WebSocket 處理外,Ktor 還支援 TCP 與 UDP 原始 Socket。 它提供了一個暫停式 API,底層使用的是 java.nio。
Socket 使用的是實驗性 API,預計在未來的更新中會有所演進,並可能包含破壞性變更。
新增相依性
若要使用 Sockets,您需要在組建指令碼中包含 ktor-network 構件:
若要在用戶端使用安全 Socket,您還需要加入 io.ktor:ktor-network-tls。
伺服器
建立伺服器 Socket
若要建立伺服器 Socket,請建立 SelectorManager 執行個體,對其呼叫 SocketBuilder.tcp() 函式,然後使用 bind 將伺服器 Socket 繫結至特定埠:
val selectorManager = SelectorManager(Dispatchers.IO)
val serverSocket = aSocket(selectorManager).tcp().bind("127.0.0.1", 9002)上述程式碼片段建立了一個 TCP Socket,即 ServerSocket 執行個體。 若要建立 UDP Socket,請使用 SocketBuilder.udp()。
接受傳入連線
建立伺服器 Socket 後,您需要呼叫 ServerSocket.accept 函式,該函式會接受 Socket 連線並傳回一個已連線的 Socket(Socket 執行個體):
val socket = serverSocket.accept()取得已連線的 Socket 後,您就可以透過讀取或寫入該 Socket 來接收/傳送資料。
接收資料
若要從用戶端接收資料,您需要呼叫 Socket.openReadChannel 函式,這會傳回 ByteReadChannel:
val receiveChannel = socket.openReadChannel()ByteReadChannel 提供了用於非同步讀取資料的 API。 例如,您可以使用 ByteReadChannel.readUTF8Line 讀取一行 UTF-8 字元:
val name = receiveChannel.readUTF8Line()傳送資料
若要將資料傳送至用戶端,請呼叫 Socket.openWriteChannel 函式,這會傳回 ByteWriteChannel:
val sendChannel = socket.openWriteChannel(autoFlush = true)ByteWriteChannel 提供了用於非同步寫入位元組序列的 API。 例如,您可以使用 ByteWriteChannel.writeStringUtf8 寫入一行 UTF-8 字元:
val name = receiveChannel.readUTF8Line()
sendChannel.writeStringUtf8("Hello, $name!
")關閉 Socket
若要釋放與已連線 Socket 相關聯的資源,請呼叫 Socket.close:
socket.close()範例
下方的程式碼範例示範了如何在伺服器端使用 Socket:
package com.example
import io.ktor.network.selector.*
import io.ktor.network.sockets.*
import io.ktor.utils.io.*
import kotlinx.coroutines.*
fun main(args: Array<String>) {
runBlocking {
val selectorManager = SelectorManager(Dispatchers.IO)
val serverSocket = aSocket(selectorManager).tcp().bind("127.0.0.1", 9002)
println("Server is listening at ${serverSocket.localAddress}")
while (true) {
val socket = serverSocket.accept()
println("Accepted ${socket.remoteAddress}")
launch {
val receiveChannel = socket.openReadChannel()
val sendChannel = socket.openWriteChannel(autoFlush = true)
sendChannel.writeStringUtf8("Please enter your name
")
try {
while (true) {
val name = receiveChannel.readUTF8Line()
sendChannel.writeStringUtf8("Hello, $name!
")
}
} catch (e: Throwable) {
socket.close()
}
}
}
}
}您可以在此處找到完整的範例:sockets-server。
用戶端
建立 Socket
若要建立用戶端 Socket,請建立 SelectorManager 執行個體,對其呼叫 SocketBuilder.tcp() 函式,然後使用 connect 建立連線並取得一個已連線的 Socket(Socket 執行個體):
val selectorManager = SelectorManager(Dispatchers.IO)
val socket = aSocket(selectorManager).tcp().connect("127.0.0.1", 9002)取得已連線的 Socket 後,您就可以透過讀取或寫入該 Socket 來接收/傳送資料。
建立安全 Socket (SSL/TLS)
安全 Socket 允許您建立 TLS 連線。 若要使用安全 Socket,您需要加入 ktor-network-tls 相依性。 然後,在已連線的 Socket 上呼叫 Socket.tls 函式:
val selectorManager = SelectorManager(Dispatchers.IO)
val socket = aSocket(selectorManager).tcp().connect("127.0.0.1", 8443).tls()tls 函式允許您調整 TLSConfigBuilder 提供的 TLS 參數:
val selectorManager = SelectorManager(Dispatchers.IO)
val socket = aSocket(selectorManager).tcp().connect("youtrack.jetbrains.com", port = 443).tls(coroutineContext = coroutineContext) {
trustManager = object : X509TrustManager {
override fun getAcceptedIssuers(): Array<X509Certificate?> = arrayOf()
override fun checkClientTrusted(certs: Array<X509Certificate?>?, authType: String?) {}
override fun checkServerTrusted(certs: Array<X509Certificate?>?, authType: String?) {}
}
}您可以在此處找到完整的範例:sockets-client-tls。
接收資料
若要從伺服器接收資料,您需要呼叫 Socket.openReadChannel 函式,這會傳回 ByteReadChannel:
val receiveChannel = socket.openReadChannel()ByteReadChannel 提供了用於非同步讀取資料的 API。 例如,您可以使用 ByteReadChannel.readUTF8Line 讀取一行 UTF-8 字元:
val greeting = receiveChannel.readUTF8Line()傳送資料
若要將資料傳送至伺服器,請呼叫 Socket.openWriteChannel 函式,這會傳回 ByteWriteChannel:
val sendChannel = socket.openWriteChannel(autoFlush = true)ByteWriteChannel 提供了用於非同步寫入位元組序列的 API。 例如,您可以使用 ByteWriteChannel.writeStringUtf8 寫入一行 UTF-8 字元:
val myMessage = readln()
sendChannel.writeStringUtf8("$myMessage
")關閉連線
若要釋放與已連線 Socket 相關聯的資源,請呼叫 Socket.close 與 SelectorManager.close:
socket.close()
selectorManager.close()範例
下方的程式碼範例示範了如何在用戶端端使用 Socket:
package com.example
import io.ktor.network.selector.*
import io.ktor.network.sockets.*
import io.ktor.utils.io.*
import kotlinx.coroutines.*
import kotlin.system.*
fun main(args: Array<String>) {
runBlocking {
val selectorManager = SelectorManager(Dispatchers.IO)
val socket = aSocket(selectorManager).tcp().connect("127.0.0.1", 9002)
val receiveChannel = socket.openReadChannel()
val sendChannel = socket.openWriteChannel(autoFlush = true)
launch(Dispatchers.IO) {
while (true) {
val greeting = receiveChannel.readUTF8Line()
if (greeting != null) {
println(greeting)
} else {
println("Server closed a connection")
socket.close()
selectorManager.close()
exitProcess(0)
}
}
}
while (true) {
val myMessage = readln()
sendChannel.writeStringUtf8("$myMessage
")
}
}
}您可以在此處找到完整的範例:sockets-client。
