程式複製到 MainActivity.kt:
package com.example.simplehttp
import android.os.Bundle
import android.net.wifi.WifiManager
import androidx.appcompat.app.AppCompatActivity
import java.net.ServerSocket
import java.net.Socket
import java.net.SocketTimeoutException
import java.io.IOException
import java.io.PrintWriter
import java.util.*
import kotlinx.coroutines.*
typealias _ReplyURI = (Socket) -> Unit
class MainActivity : AppCompatActivity() {
private val patternBegin = "GET "
private val patternEnd = " HTTP/1.1"
private val hformat = "HTTP/1.0 200 OK\nServer: Simple\nContent-Type: %s\nContent-Length: %11d\nConnection: close\n\n"
private val socketPrintHTML:(Socket, String) -> Unit = {sfd, html ->
try {
val writer = PrintWriter(sfd.getOutputStream(), true)
writer.printf(hformat, "text/html", html.length)
writer.printf("%s", html)
} catch (e: IOException) {
e.printStackTrace()
}
}
data class OneResponse(val uri:String, val lambda: _ReplyURI)
inner class ToResponse(val fd: Socket) {
private val field = ArrayList<OneResponse>()
private val lambdaNull: _ReplyURI = { socketPrintHTML(it, "is lambda Null ok?") }
val execute:(String) -> Unit = { uri ->
if(! fd.isClosed) {
val matchURI = uri.toLowerCase()
for(i in field.indices) if(field[i].uri == matchURI) {
field[i].lambda(fd)
}
socketPrintHTML(fd, "not found $uri")
}
}
fun toReply(uri:String, lambda:_ReplyURI? = null) {
field.add(OneResponse(
uri.toLowerCase(),
lambda ?: lambdaNull
))
}
}
private fun uhttpRequest(res:ToResponse) {
val rxSize = 1024
val rxBuffer = ByteArray(rxSize)
val len = res.fd.getInputStream().read(rxBuffer, 0, rxSize - 1)
if(len > 0) {
rxBuffer[len] = 0
val str = String(rxBuffer)
if (str.startsWith(patternBegin) && str.contains(patternEnd)) res.
execute( str.substring( patternBegin.length, str.indexOf(patternEnd) ))
}
}
private lateinit var serverJob: Job
private var portTCP: Int = 8080
private var snapURI: String = "/"
private fun uListen() {
var streamingLock = false
val tcpServer = ServerSocket(portTCP).apply {
soTimeout = 40
}
while (serverJob.isActive) {
try {
val socketfd = tcpServer.accept()
val req = ToResponse(socketfd). apply {
toReply("/Hello1")
toReply("/Hello2") { sfd ->
socketPrintHTML(sfd, "You are welcome")
}
toReply(snapURI) { sfd -> runBlocking {
while(streamingLock) delay(100)
streamingLock = true //...
socketPrintHTML(sfd, "Coroutine runBlocking ok")
streamingLock = false
}}
}
GlobalScope.launch(Dispatchers.IO) {
uhttpRequest(req)
socketfd.close()
}
} catch (e: SocketTimeoutException) {
}
}
tcpServer.close()
}
override fun onResume() {
val info = (applicationContext.
getSystemService(WIFI_SERVICE) as WifiManager).connectionInfo
val a = info.ipAddress and 0xff
val b = info.ipAddress shr 8 and 0xff
val c = info.ipAddress shr 16 and 0xff
val d = info.ipAddress shr 24 and 0xff
title = "http://$a.$b.$c.$d:${portTCP}${snapURI}"
serverJob = GlobalScope.launch(Dispatchers.IO) {
uListen()
}
}
override fun onPause() {
runBlocking {
serverJob.cancelAndJoin()
}
super.onPause()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
}
}
}
沒有留言:
張貼留言