本地socket连接

# socket_client
import socket

client = socket.socket()  #申明socket类型 同时生成socket链接对象

client.connect(('localhost', 6969))

client.send(b"hello world") #所有的数据传输接受都需要使用bytes类型 中文 encode("utf-8")
data = client.recv(1024)

print("receive:", data)

client.close()


# socket_server
import socket

server = socket.socket()

server.bind(('localhost', 6969))
server.listen()

print("我要开始等电话了")
# server.accept()
conn,addr = server.accept() #conn就是客户端链接过来而在服务器端为其生成的一个连接实例
print(conn,addr)

print("电话来了")
data = conn.recv(1024)
print("recv:", data)
conn.send(data.upper())

server.close()

<think>我们将在Android应用中使用Kotlin创建本地Socket连接(即客户端与服务器在同一设备上通信)。通常,本地服务器监听`localhost`(127.0.0.1)或设备的内网IP。但更常见的是使用回环地址127.0.0.1,避免权限问题。 步骤概述: 1. 添加网络权限 2. 创建服务器端(可选,如果已有服务器可跳过) 3. 创建客户端连接 4. 处理连接异常 注意:在Android中,网络操作不能在主线程执行,需使用后台线程或协程。 参考引用[1]和[4],我们使用Socket类实现TCP连接。引用[3]提到长连接框架OkSocket,但这里我们使用标准库实现。 详细步骤: ### 1. 添加网络权限 在`AndroidManifest.xml`中添加: ```xml <uses-permission android:name="android.permission.INTERNET" /> ``` 注意:即使使用本地地址(127.0.0.1),也需要此权限。 ### 2. 创建简单的本地服务器(可选) 如果还没有服务器,可以创建一个简单的服务器用于测试。在Android中,我们可以在后台线程中创建服务器。 参考引用[2],使用`ServerSocket`创建服务器: ```kotlin import java.io.BufferedReader import java.io.InputStreamReader import java.io.PrintWriter import java.net.ServerSocket import kotlinx.coroutines.* // 在协程中启动服务器 fun startServer(port: Int) { CoroutineScope(Dispatchers.IO).launch { try { val serverSocket = ServerSocket(port) println("服务器启动,等待客户端连接...") while (true) { val clientSocket = serverSocket.accept() // 阻塞直到有客户端连接 // 为每个客户端连接启动一个协程 launch { handleClient(clientSocket) } } } catch (e: Exception) { e.printStackTrace() } } } private fun handleClient(clientSocket: Socket) { try { val input = BufferedReader(InputStreamReader(clientSocket.getInputStream())) val output = PrintWriter(clientSocket.getOutputStream(), true) // 读取客户端消息 val message = input.readLine() println("收到客户端消息: $message") // 回复客户端 output.println("服务器已收到你的消息: $message") // 关闭连接(如果是短连接) clientSocket.close() } catch (e: Exception) { e.printStackTrace() } } ``` ### 3. 创建客户端连接 客户端使用`Socket`连接服务器。同样在后台线程中执行。 ```kotlin import java.io.BufferedReader import java.io.InputStreamReader import java.io.PrintWriter import java.net.Socket import kotlinx.coroutines.* fun connectToServer(port: Int, message: String) { CoroutineScope(Dispatchers.IO).launch { try { // 连接本地服务器,127.0.0.1表示本机 val socket = Socket("127.0.0.1", port) // 发送消息 val output = PrintWriter(socket.getOutputStream(), true) output.println(message) // 接收服务器响应 val input = BufferedReader(InputStreamReader(socket.getInputStream())) val response = input.readLine() println("服务器响应: $response") // 关闭连接 socket.close() } catch (e: Exception) { e.printStackTrace() } } } ``` ### 4. 使用示例 假设我们在Activity中启动服务器(端口设为8888),然后客户端连接并发送消息。 ```kotlin class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 启动服务器 startServer(8888) // 模拟客户端连接(延迟2秒,确保服务器已启动) CoroutineScope(Dispatchers.IO).launch { delay(2000) connectToServer(8888, "Hello Server!") } } } ``` ### 5. 注意事项 - **端口冲突**:如果出现`BindException: Address already in use`,说明端口被占用。可更换端口或确保之前占用端口的进程已关闭(参考用户之前的问题)。 - **长连接**:上述示例为短连接(发送一次消息后关闭)。如需长连接,客户端和服务器应保持Socket打开,并持续通信(参考引用[4])。 - **线程安全**:在Android中,网络操作必须在后台线程(或协程的IO调度器)中进行,否则会抛出`NetworkOnMainThreadException`。 - **异常处理**:网络操作可能失败(如连接超时、端口未打开等),需捕获异常并重试或提示用户。 ### 6. 长连接实现要点 若需长连接,可修改客户端和服务器端的处理逻辑: - 客户端:循环发送消息,并保持Socket不关闭。 - 服务器端:为每个客户端连接创建一个循环,持续读取消息并回复。 但要注意:长时间保持连接可能消耗资源,需在适当时候(如应用退出)关闭连接。 参考引用[3]提到的OkSocket框架,它提供了长连接管理和自动重连等功能,适合生产环境。但基础学习使用标准库即可。 以上代码仅为示例,实际应用中需根据业务需求调整。 相关问题: 1. Android中如何实现Socket连接? 2. Kotlin协程在Socket通信中如何应用? 3. 如何避免Android Socket连接中的端口冲突? 4. 使用OkSocket框架有什么优势? 引用说明: [^1]: Android实现socket Tcp长连接 (附完整源码) [^2]: 使用Kotlin编写一个Http服务器 [^3]: Android实现Socket连接 , OkSocket框架简单使用 [^4]: 简单的Kotlin使用Socket与服务端进行通信</think>### Kotlin Android 创建本地Socket连接指南 在Android平台上使用Kotlin建立本地Socket连接(客户端与服务器在同一设备)的完整实现如下: #### 1. 添加权限与依赖 在`AndroidManifest.xml`中添加网络权限: ```xml <uses-permission android:name="android.permission.INTERNET" /> ``` #### 2. 创建Socket服务器端 ```kotlin import java.net.ServerSocket import kotlinx.coroutines.* class LocalSocketServer(private val port: Int) { private var serverSocket: ServerSocket? = null private val serverJob = Job() private val serverScope = CoroutineScope(Dispatchers.IO + serverJob) fun start() { serverScope.launch { try { // 创建服务器Socket并设置端口重用 serverSocket = ServerSocket().apply { reuseAddress = true bind(InetSocketAddress("127.0.0.1", port)) } Log.d("SocketServer", "服务器启动,监听端口: $port") while (isActive) { val clientSocket = serverSocket?.accept() clientSocket?.let { handleClient(it) } } } catch (e: Exception) { Log.e("SocketServer", "服务器错误: ${e.message}") } } } private fun handleClient(clientSocket: Socket) { CoroutineScope(Dispatchers.IO).launch { try { val reader = BufferedReader(InputStreamReader(clientSocket.getInputStream())) val message = reader.readLine() Log.d("SocketServer", "收到客户端消息: $message") // 回复客户端 val writer = PrintWriter(clientSocket.getOutputStream(), true) writer.println("服务器已收到: $message") } finally { clientSocket.close() } } } fun stop() { serverJob.cancel() serverSocket?.close() Log.d("SocketServer", "服务器已关闭") } } ``` #### 3. 创建Socket客户端 ```kotlin import java.net.Socket import kotlinx.coroutines.* class LocalSocketClient(private val port: Int) { fun sendMessage(message: String) { CoroutineScope(Dispatchers.IO).launch { try { // 连接本地服务器 Socket("127.0.0.1", port).use { socket -> // 发送消息 PrintWriter(socket.getOutputStream(), true).apply { println(message) flush() } // 接收响应 BufferedReader(InputStreamReader(socket.getInputStream())).apply { val response = readLine() Log.d("SocketClient", "服务器响应: $response") } } } catch (e: Exception) { Log.e("SocketClient", "连接错误: ${e.message}") } } } } ``` #### 4. 在Activity中使用 ```kotlin class MainActivity : AppCompatActivity() { private lateinit var socketServer: LocalSocketServer private lateinit var socketClient: LocalSocketClient private val PORT = 8888 // 使用高位端口 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 启动服务器 socketServer = LocalSocketServer(PORT) socketServer.start() // 初始化客户端 socketClient = LocalSocketClient(PORT) // 发送消息按钮 findViewById<Button>(R.id.btn_send).setOnClickListener { socketClient.sendMessage("Hello from client at ${System.currentTimeMillis()}") } } override fun onDestroy() { super.onDestroy() socketServer.stop() // 确保关闭服务器 } } ``` #### 5. 注意事项 1. **端口选择**: - 使用高位端口(10000-65535),避免系统端口冲突 - 动态端口分配:`ServerSocket(0)`让系统自动分配空闲端口 2. **异常处理**: - 捕获`BindException`处理端口占用问题 - 使用`try-catch`处理网络超时和中断 3. **生命周期管理**: - 在`onDestroy()`中关闭服务器Socket - 使用协程作用域管理后台任务 4. **线程安全**: - 所有网络操作在`Dispatchers.IO`线程执行 - 使用`CoroutineScope`管理并发任务 5. **本地地址**: - 使用`127.0.0.1`或`localhost`指向设备自身 - 避免使用外部IP,确保仅在设备内部通信 #### 端口冲突解决方案 如果遇到`EADDRINUSE`错误(端口被占用): 1. 在服务器启动前查端口可用性: ```kotlin fun isPortAvailable(port: Int): Boolean { return try { ServerSocket(port).close() true } catch (e: IOException) { false } } ``` 2. 自动重试机制: ```kotlin fun startWithRetry(maxRetries: Int = 3) { var retryCount = 0 while (retryCount < maxRetries) { if (isPortAvailable(PORT)) { start() return } retryCount++ Thread.sleep(1000) } Log.e("SocketServer", "无法绑定端口$PORT") } ``` 3. 动态端口分配: ```kotlin val dynamicPort = findAvailablePort(10000, 20000) fun findAvailablePort(start: Int, end: Int): Int { for (port in start..end) { if (isPortAvailable(port)) return port } throw IllegalStateException("无可用端口") } ``` #### 完整工作流程 1. 服务器启动监听指定端口 2. 客户端连接`127.0.0.1:PORT` 3. 客户端发送消息并等待响应 4. 服务器接收消息并返回确认 5. 连接关闭(短连接)或保持(长连接) 对于长连接实现,需要: - 保持Socket不关闭 - 实现心跳机制 - 使用双工通信(读写分离线程) - 添加超时测[^3][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值