如何通过 Kotlin 在 Android 中使用套接字
Posted
技术标签:
【中文标题】如何通过 Kotlin 在 Android 中使用套接字【英文标题】:How to use socket in Android with Kotlin 【发布时间】:2021-06-18 19:10:01 【问题描述】:我想在 android 中使用 Kotlin 实现一些目标:
如果我单击应用程序上的按钮,应用程序会向 TCP 服务器(我用 python 编写)发送一个字。服务器将返回另一个单词,应用程序将显示一条 toast 消息。
这是我到目前为止所做的,我可以弄清楚发送部分,但我无法让它继续监听套接字以接收来自服务器的消息。
我正在尝试使用协程,但是在网上找到所有资源后,这是我能得到的最好的。
另外,我不确定我是否以正确的方式设置 IP 地址。
提前感谢您的帮助!
'''
class MainActivity : AppCompatActivity()
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val sendBtn = findViewById<Button>(R.id.sendBtn )
val ipBtn = findViewById<Button>(R.id.ipBtn)
val ipInput = findViewById<TextView>(R.id.ipInput)
var ipAddress: String = "192.168.0.101"
// Below is my attempt to keep listening to the socket, if commented, the sending would work.
// My guess is the IO thread is caught in the while loop so the other coroutines cannot use
// IO thread to send to the server.
CoroutineScope(IO).launch
val socket = Socket(ipAddress, 9999)
var text = ""
while (true)
text = BufferedReader(InputStreamReader(socket.inputStream)).readLine()
// if text is not null
// Toast.makeText(this@MainActivity, "Set IP", Toast.LENGTH_SHORT).show()
suspend fun sendMessage(message:String)
val socket = Socket(ipAddress, 9999)
socket.outputStream.write(message.toByteArray())
socket.close()
ipBtn.setOnClickListener
Toast.makeText(this@MainActivity, "Set IP", Toast.LENGTH_SHORT).show()
ipAddress = ipInput.text.toString()
sendBtn .setOnClickListener
CoroutineScope(IO).launch
Log.d("TAG", "message")
sendMessage("record")
'''
【问题讨论】:
解决方案可能是使用线程。这是一个很好的(Java)示例:Sending and Receiving Data with Sockets in android @paulsm4 感谢您的建议。我了解到,对于互联网通信,建议使用协程(例如从 API 获取数据)。你能解释一下为什么在我的情况下线程比协程更受欢迎吗? 【参考方案1】:要从 P2P Fist 发送数据,我们需要一个 Server 和 Client 。在这里,Socket 充当了通过网络发送和接收数据的端点。
-
像这样创建一个服务器类
class ServerClass() :Thread()
lateinit var serverSocket:ServerSocket
lateinit var inputStream: InputStream
lateinit var outputStream: OutputStream
lateinit var socket: Socket
override fun run()
try
serverSocket = ServerSocket(8888)
socket = serverSocket.accept()
inputStream =socket.getInputStream()
outputStream = socket.getOutputStream()
catch (ex:IOException)
ex.printStackTrace()
val executors = Executors.newSingleThreadExecutor()
val handler = Handler(Looper.getMainLooper())
executors.execute(Runnable
kotlin.run
val buffer = ByteArray(1024)
var byte:Int
while (true)
try
byte = inputStream.read(buffer)
if(byte > 0)
var finalByte = byte
handler.post(Runnable
kotlin.run
var tmpMeassage = String(buffer,0,finalByte)
Log.i("Server class","$tmpMeassage")
)
catch (ex:IOException)
ex.printStackTrace()
)
fun write(byteArray: ByteArray)
try
Log.i("Server write","$byteArray sending")
outputStream.write(byteArray)
catch (ex:IOException)
ex.printStackTrace()
-
在我们需要传递主机地址的地方创建一个客户端类
class ClientClass(hostAddress: InetAddress): Thread()
var hostAddress: String = hostAddress.hostAddress
lateinit var inputStream: InputStream
lateinit var outputStream: OutputStream
lateinit var socket: Socket
fun write(byteArray: ByteArray)
try
outputStream.write(byteArray)
catch (ex:IOException)
ex.printStackTrace()
override fun run()
try
socket = Socket()
socket.connect(InetSocketAddress(hostAddress,8888),500)
inputStream = socket.getInputStream()
outputStream = socket.getOutputStream()
catch (ex:IOException)
ex.printStackTrace()
val executor = Executors.newSingleThreadExecutor()
var handler =Handler(Looper.getMainLooper())
executor.execute(kotlinx.coroutines.Runnable
kotlin.run
val buffer =ByteArray(1024)
var byte:Int
while (true)
try
byte = inputStream.read(buffer)
if(byte>0)
val finalBytes = byte
handler.post(Runnable
kotlin.run
val tmpMeassage = String(buffer,0,finalBytes)
Log.i("client class", tmpMeassage)
)
catch (ex:IOException)
ex.printStackTrace()
)
确保服务器和客户端端口应该相同,这是双向通信,我们可以在双方传输数据。
【讨论】:
以上是关于如何通过 Kotlin 在 Android 中使用套接字的主要内容,如果未能解决你的问题,请参考以下文章
Android 上的 Kotlin:如何在片段中使用数据库中的 LiveData?
如何在 kotlin android 的活动中访问应用程序类变量
如何通过单击 Image Kotlin Android 来移动 Activity