102
社区成员
发帖
与我相关
我的任务
分享Socket,也被称为“套接字”,是应用程序用于向网络发送请求或响应网络请求的机制,它允许不同主机或同一计算机上的进程之间进行通信。
在服务端,首先进行Socket的初始化,随后将其与特定端口绑定(bind),并对该端口进行监听(listen)。此时,服务端调用accept进入阻塞状态,等待客户端的连接请求。当客户端初始化一个Socket并尝试连接到服务器(connect)时,若连接成功,即建立了客户端与服务器之间的通信链路。
客户端随后发送数据请求,服务端接收并处理这些请求,之后将响应数据发送回客户端。客户端读取这些数据后,通信双方关闭连接,至此完成一次交互过程。
在使用TCP发送数据时,由于TCP连接已经建立,因此无需指定目标地址。相比之下,UDP是面向无连接的,每次发送数据时都需要明确指定接收方。
WebView控件是Android应用中用于展现网页内容的关键组件。它能够载入并呈现Web页面,同时兼容JavaScript执行、页面交互及其他Web技术。
WebView具备加载和展示Web页面的功能,涵盖HTML、CSS、JavaScript等网页元素。
在Android应用中,WebView控件被广泛用于展示网页内容,比如作为内置浏览器使用,或在混合开发应用中展示原生和Web内容。它为开发者提供了一个强大的工具,使得应用能够展示丰富的Web内容,并实现与用户的交互。
1.掌握Android平台上Socket编程的基本概念。
2.学习使用Kotlin语言实现Android Socket服务端和客户端。
3.理解TCP/UDP协议在Socket通信中的应用。
Android Studio
Kotlin编程语言
模拟器或真实Android设备
新建两个项目,分别是服务器Server和客户端Client


(1) 创建一个新的Android项目,并在项目中添加必要的权限,如INTERNET权限。

(2)编写服务端代码,创建一个ServerSocket监听指定端口。

完整代码如下:
MainActivity.kt
package com.example.project4_server
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import androidx.activity.ComponentActivity
import java.util.concurrent.Executors
class MainActivity : ComponentActivity() {
private lateinit var server: Server
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_server)
server = Server { message ->
runOnUiThread {
displayMessage("Client: $message")
}
}
Executors.newSingleThreadExecutor().execute {
server.start()
}
val sendButton : Button = findViewById(R.id.buttonSend)
sendButton.setOnClickListener {
val messageInput : EditText = findViewById(R.id.editTextMessage)
val message = messageInput.text.toString()
if (message.isNotEmpty()) {
server.sendMessage(message)
displayMessage("Server(Me): $message")
messageInput.text.clear()
}
}
}
private fun displayMessage(message: String) {
var messageDisplay : TextView = findViewById(R.id.textViewMessage)
messageDisplay.append("$message\n")
}
override fun onDestroy() {
super.onDestroy()
server.stop()
}
}
activity_server.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<EditText
android:id="@+id/editTextMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter your message" />
<Button
android:id="@+id/buttonSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send" />
<TextView
android:id="@+id/textViewMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Received Message"
android:textStyle="bold" />
</LinearLayout>
Server.kt
package com.example.project4_server
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.PrintWriter
import java.net.ServerSocket
class Server(private val messageListener: (String) -> Unit) {
private val serverSocket = ServerSocket(2104)
private lateinit var writer: PrintWriter
private lateinit var reader: BufferedReader
fun start() {
while (true) {
val clientSocket = serverSocket.accept()
GlobalScope.launch(Dispatchers.IO) {
val outputStream = clientSocket.getOutputStream()
writer = PrintWriter(outputStream, true)
val inputStream = clientSocket.getInputStream()
reader = BufferedReader(InputStreamReader(inputStream))
writer.println("恭喜您,与客户端连接成功!!")
while (true) {
val messageFromServer = reader.readLine()
if (messageFromServer != null) {
messageListener.invoke(messageFromServer)
}
}
}
}
}
fun sendMessage(message: String) {
GlobalScope.launch(Dispatchers.IO) {
writer.println(message)
}
}
fun stop() {
serverSocket.close()
}
}
运行结果如图:

(1) 编写客户端代码,创建一个Socket对象连接服务端。

基本和服务端差不多
完整代码如下:
activity_client.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<EditText
android:id="@+id/editTextMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter your message" />
<Button
android:id="@+id/buttonSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send" />
<TextView
android:id="@+id/textViewReceivedMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Received Message"
android:textStyle="bold" />
</LinearLayout>
MainActivity.kt
package com.example.project4_client
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import androidx.activity.ComponentActivity
class MainActivity : ComponentActivity() {
private lateinit var client: Client
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_client)
client = Client { message ->
runOnUiThread {
displayMessage("Server: $message")
}
}
client.connect()
val sendButton : Button = findViewById(R.id.buttonSend)
sendButton.setOnClickListener {
val messageInput : EditText = findViewById(R.id.editTextMessage)
val message = messageInput.text.toString()
if (message.isNotEmpty()) {
client.sendMessage(message)
displayMessage("Client(Me): $message")
messageInput.text.clear()
}
}
}
private fun displayMessage(message: String) {
var messageDisplay : TextView = findViewById(R.id.textViewReceivedMessage)
messageDisplay.append("$message\n")
}
override fun onDestroy() {
super.onDestroy()
client.disconnect()
}
}
Cilent.kt
package com.example.project4_client
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.PrintWriter
import java.net.Socket
import kotlinx.coroutines.*
class Client(private val messageListener: (String) -> Unit) {
private lateinit var clientSocket: Socket
private lateinit var writer: PrintWriter
private lateinit var reader: BufferedReader
fun connect() {
GlobalScope.launch(Dispatchers.IO) {
clientSocket = Socket("192.168.31.137", 2104)
val outputStream = clientSocket.getOutputStream()
writer = PrintWriter(outputStream, true)
writer.println("恭喜您,与服务器连接成功!!")
val inputStream = clientSocket.getInputStream()
reader = BufferedReader(InputStreamReader(inputStream))
while (true) {
val messageFromServer = reader.readLine()
if (messageFromServer != null) {
messageListener.invoke(messageFromServer)
}
}
}
}
fun sendMessage(message: String) {
GlobalScope.launch(Dispatchers.IO) {
writer.println(message)
}
}
fun disconnect() {
writer.close()
reader.close()
clientSocket.close()
}
}
最终效果如下方视频所示(失败了):
问题1:想要用两个虚拟设备,一个作客户端,一个作服务器端,但是第二个虚拟设备始终无法正常启动

通过本次实验,我深刻领悟了Android平台上Socket编程的核心概念,并掌握了如何在Android应用开发中运用Kotlin语言实现Socket的服务端与客户端功能。我熟悉了ServerSocket类和Socket类的基本应用,其中ServerSocket用于在服务端监听特定端口,而Socket则用于在客户端与服务端之间建立连接。此外,我还学会了在Socket编程中如何发送与接收数据,涵盖了字符串数据的发送与接收,以及利用输入输出流进行数据交换的技巧。
实验结束后,虽然没能成功,但是我对Android平台上的Socket编程有了更为深刻的理解,并掌握了实际应用中的开发技能与实战经验。同时,这次实验也加深了我对TCP/UDP协议在Socket通信中所起作用的理解,为我未来在网络编程领域的进一步工作与学习奠定了坚实的基础。