1.添加用户权限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
在主窗口的初始化位置添加权限获取代码
var permissions1= arrayOf(
Manifest.permission.ACCESS_WIFI_STATE,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_NETWORK_STATE,
)
if((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED)||
(ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED)||
(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)
) {
ActivityCompat.requestPermissions(this, permissions1,1,)
} else {
// 权限已授权,执行相应操作
Log.d("scoreInfo","权限已授权,执行相应操作2")
}
2.添加库
添加lifecycle.viewmodel库
3.创建ViewModel供界面调用
import androidx.lifecycle.ViewModel
import androidx.media3.common.util.Log
import androidx.media3.common.util.UnstableApi
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.getAndUpdate
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import java.net.ServerSocket
import java.net.Socket
@androidx.annotation.OptIn(UnstableApi::class)
class TcpServerViewModel: ViewModel() {
lateinit var tcpServer: TcpServerThread
init {
StartTcpServer(3000)
}
fun StartTcpServer(port: Int) {
try {
tcpServer = TcpServerThread(port)
tcpServer.start()
} catch (e: Exception) {
e.printStackTrace()
} finally {
}
}
}
3.创建TcpServerThread
import androidx.compose.runtime.mutableStateListOf
import java.net.InetAddress
import java.net.ServerSocket
import java.net.Socket
import java.util.concurrent.locks.ReentrantLock
class TcpServerThread(private val port:Int):Thread() {
val socketList:MutableList<SocketData> = mutableStateListOf()
private final var lock :ReentrantLock= ReentrantLock()
override fun run() {
try{
val serverSocket = ServerSocket(port)
println("Server is listening on port $port")
while (true) {
val clientSocket: Socket = serverSocket.accept() // 阻塞直到连接建立
println("New client connected: ${clientSocket.remoteSocketAddress}")
//查看当前的连接链表,如果有相同的IP,则关闭接收线程,关闭连接。
for( socketData in socketList){
if(socketData.socket.inetAddress.toString() == clientSocket.inetAddress.toString()){
var socket = socketData.socket
socketData.handler.interrupt()
socket.close()
}
}
val clientThread = ClientHandler(clientSocket,socketList,lock)
var client = SocketData(clientSocket,clientThread,false,0)
lock.lock()
socketList.add(client)
lock.unlock()
clientThread.start() // 处理每个客户端连接的新线程
}
}
catch (e:Exception){
e.printStackTrace()
}
finally {
}
}
//添加停止函数
fun StopServer(){
lock.lock()
for(socketData in socketList) {
socketData.handler.interrupt()
socketData.socket.close()
}
socketList.clear()
lock.unlock()
}
}
4.创建ClientHandler
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.Socket
import java.nio.Buffer
class ClientHandler(private val clientSocket: Socket,var socketList:MutableList<SocketData>,var lock :ReentrantLock ):Thread() {
override fun run() {
try {
val input = clientSocket.getInputStream()
var buffer = ByteArray(1024)
var line: String?
while (true) {
val readBytes = input.read(buffer)
if(readBytes<=0)
{
try{
sleep(10)
}
catch(e:Exception)
{
e.printStackTrace()
}
break
}
else {
line = String(buffer.copyOfRange(0,readBytes))
println("Received from client: ${line}")
}//if (line == null || line.isEmpty()) break // 客户端断开连接或无数据时退出循环
try{
sleep(10)
}
catch(e:Exception)
{
e.printStackTrace()
}
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
lock.lock()
try {
if(socketList.size>0) {
for (socketdata in socketList) {
if (clientSocket.inetAddress.toString() == socketdata.socket.inetAddress.toString()) {
socketList.remove(socketdata)
}
}
Log.d("score", socketList.toString())
clientSocket.close() // 关闭套接字连接
}
}catch (e: Exception)
{
e.printStackTrace()
}
lock.unlock()
}
}
}
4.添加一些辅助类
import java.net.Socket
data class SocketData (
var socket: Socket,
var handler: ClientHandler,
var RemoveState:Boolean,
var barid:Int
)
5.调用测试
在compose界面中获取viewmodel变量。
val tcpViewModel = ViewModelProvider(this).get(TcpServerViewModel::class.java)
在界面初始化或按钮点击事件中调用。
tcpViewModel.StartTcpServer(3000)

3745

被折叠的 条评论
为什么被折叠?



