Socket的具体使用
TCP:
首先服务端创建一个ServerSocket,并绑定目标端口,然后循环调用accept方法,这个方法用于监听客户端的连接,它是阻塞的,当收到连接后继续执行,这时创建一个新的线程,用于为这个客户端提供服务,然后重新循环刚才的流程。
客户端创建一个Socket,并设置ip或目标主机地址和端口号。然后使用这个socket获取输出流,将要发送的数据写入输出流,最后使用socket执行shutdownOutput关闭输出流,这时数据就发送出去了。如果是接收数据,那么需要获取输入流,并读取输入流的数据。完成操作后需要close关闭流,否则会导致资源浪费和异常。
具体代码:
Server
| |
| val serverSocket = ServerSocket(8888) |
| var socket: Socket? |
| |
| var count = 0 |
| println("***服务器即将启动,等待客户端的连接***") |
| |
| while (true) { |
| |
| socket = serverSocket.accept() |
| |
| val serverThread = ServerThread(socket) |
| |
| serverThread.start() |
| count++ |
| KLog.d(msg = "客户端的数量:$count") |
| val address: InetAddress = socket.inetAddress |
| KLog.d(msg = "当前客户端的IP:" + address.hostAddress) |
| } |
Client
| |
| val socket = Socket("localhost", 8888) |
| |
| val os: OutputStream = socket.getOutputStream() |
| val pw = PrintWriter(os) |
| pw.write("用户名:whf;密码:789") |
| pw.flush() |
| socket.shutdownOutput() |
| |
| val inputStream: InputStream = socket.getInputStream() |
| val br = BufferedReader(InputStreamReader(inputStream)) |
| var info: String? |
| while (br.readLine().also { info = it } != null) { |
| KLog.d(msg = "我是客户端,服务器说:$info") |
| } |
| |
| br.close() |
| inputStream.close() |
| pw.close() |
| os.close() |
| socket.close() |
UDP:
首先创建一个DatagramSocket,并绑定目标端口,然后创建一个字节数组用于读取接收的数据,调用receive接收客户端的数据,这个方法是阻塞的。它还有另一个方法send,用于发送数据。
客户端创建一个 DatagramSocket,然后设置服务器主机地址和端口号。然后将需要发送的数据包装成数据包DatagramPacket对象,通过send发送。
具体代码
Server
| |
| val ds = DatagramSocket(12345) |
| |
| |
| |
| |
| |
| val data = ByteArray(1024) |
| val dp = DatagramPacket(data, data.size) |
| ds.receive(dp) |
| |
| val str = String(data, 0, dp.length) |
| println(str) |
| |
| ds.close() |
Client
| |
| |
| |
| |
| |
| val ds = DatagramSocket() |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| val str = "你好,UDP" |
| val ch = str.toByteArray() |
| val dp = DatagramPacket(ch, ch.size) |
| dp.socketAddress = InetSocketAddress("127.0.0.1", 12345) |
| |
| ds.send(dp) |
| |
| ds.close() |
ServerThread
| private class ServerThread(socket: Socket?) : Thread() { |
| |
| private var socket: Socket? = null |
| |
| override fun run() { |
| var inputStream: InputStream? = null |
| var isr: InputStreamReader? = null |
| var br: BufferedReader? = null |
| var os: OutputStream? = null |
| var pw: PrintWriter? = null |
| try { |
| |
| inputStream = socket!!.getInputStream() |
| isr = InputStreamReader(inputStream!!) |
| br = BufferedReader(isr) |
| var info: String? |
| while (br.readLine().also { info = it } != null) { |
| KLog.d(msg = "我是服务器,客户端说:$info") |
| } |
| socket!!.shutdownInput() |
| |
| os = socket!!.getOutputStream() |
| pw = PrintWriter(os) |
| pw.write("欢迎您!") |
| pw.flush() |
| } catch (e: IOException) { |
| e.printStackTrace() |
| } finally { |
| |
| try { |
| pw?.close() |
| os?.close() |
| br?.close() |
| isr?.close() |
| inputStream?.close() |
| if (socket != null) socket!!.close() |
| } catch (e: IOException) { |
| e.printStackTrace() |
| } |
| } |
| } |
| init { |
| this.socket = socket |
| } |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)