先看下效果:
基本原理:
1.客户端初始化socket,服务端初始化ServerSocket,定义IP和端口
2.服务端开启一个死循环,通过accept阻塞线程输入流不断的接收客户端的数据
3.客户端通过输出流发送数据给服务端
4.服务端通过输入流获取数据后,通过输出流把数据转发出去
5.客户端通过数据流获取服务端返回的数据。
然后了解下Java中的赋值表达式转为Kotlin吧
while ((len = inputStream.read(buf)) != -1) {}
转为kotlin就是
while (inputStream.read(buf).let { len = it;it != -1 }) {}
进入正题
创建一个ISocket.kt文件
package com.i.mvvmdemo
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.net.InetAddress
import java.net.ServerSocket
import java.net.Socket
import java.util.*
-----------------------------------服务端----------------------------------
class Server constructor(port: Int) : Thread() {
private var list: MutableList<Socket> = ArrayList()
private var server: ServerSocket
init {
val inetAddress = InetAddress.getByName("192.168.31.48")
server = ServerSocket(port, 50, inetAddress)
}
override fun run() {
super.run()
try {
while (true) {
val socket = server.accept()
val message = socket.inetAddress.hostAddress.toString()
println("$message == Connected")
SendMessageToAllUser(message)
list.add(socket)
readerThread(socket).start()
}
} catch (e: IOException) {
e.printStackTrace()
}
}
private fun SendMessageToAllUser(message: String) {
for (socket in list) {
if (socket != null && socket.isConnected) {
try {
val os = socket.getOutputStream()
os.write(message.toByteArray())
os.flush()
} catch (e: IOException) {
e.printStackTrace()
}
}
}
}
inner class readerThread(socket: Socket) : Thread() {
lateinit var inputStream: InputStream
init {
try {
// 获取输入流
inputStream = socket.getInputStream()
} catch (e: IOException) {
e.printStackTrace()
}
}
override fun run() {
super.run()
try {
var inputStream: InputStream = inputStream
var len = 0
val buf = ByteArray(1024)
while (inputStream.read(buf).let { len = it;it != -1 }) {
println("Server receives data from client: " + String(buf, 0, len))
SendMessageToAllUser(String(buf, 0, len))
}
} catch (e: IOException) {
e.printStackTrace()
}
}
}
}
-----------------------------------客户端------------------------------------
class Client constructor(host: String, port: Int) : Thread() {
var socket: Socket
init {
socket = Socket(host, port)
}
override fun run() {
super.run()
sendMessThread().start()
super.run()
try {
// 读Sock里面的数据
val inputStream = socket.getInputStream()
val buf = ByteArray(1024)
var len = 0
while (inputStream.read(buf).let { len = it;it != -1 }) {
println(String(buf, 0, len))
}
} catch (e: IOException) {
e.printStackTrace()
}
}
inner class sendMessThread : Thread() {
override fun run() {
super.run()
//写操作
var scanner: Scanner? = null
var os: OutputStream? = null
try {
scanner = Scanner(System.`in`)
os = socket.getOutputStream()
var input = ""
do {
input = scanner.next()
os!!.write("client:$input".toByteArray())
os.flush()
} while (input != "bye")
} catch (e: IOException) {
e.printStackTrace()
}
scanner?.close()
try {
os?.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
}
}
--------------------------------------测试----------------------------------
fun main() {
startServer()
startClient()
}
fun startServer() {
Server(6768).start()
}
fun startClient() {
//你电脑本地的ip,端口号随便设置
Client("192.168.31.48", 6768).start()
}
由于一个kt文件只能有一个main方法,所以再创建一个kt文件
ClientB.kt
------------------------------测试(开第二个客户端)-------------------------
fun main(){
startClient()
}
参考:https://blog.csdn.net/wenzhi20102321/article/details/52620323