【2023】Kotlin教程 第三篇 Kotlin进阶 第22章 网络编程 22.3 UDP Socket低层次网络编程 22.3.3 案例:文件上传工具

该文章是Kotlin教程的进阶部分,讲解了如何使用UDPSocket进行低层次的网络编程。与基于TCP的Socket相比,UDP无连接且不保证数据顺序,但适合实时性要求高的场景。文章通过一个文件上传工具的案例,展示了在服务器端和客户端如何利用UDPSocket实现文件传输,并强调了通过发送特定标志(如bye)来指示传输结束的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【2023】Kotlin教程

在这里插入图片描述

第三篇 Kotlin进阶

第22章 网络编程

现代的应用程序都离不开网络,网络编程是非常重要的技术。Kotlin标准库网络编程源自于Java提供java.net包,其中包含了网络编程所需要的最基础一些类和接口。这些类和接口面向两个不同的层次:

  1. 基于Socket的低层次网络编程。Socket采用TCP、UDP等协议,这些协议属于低层次的通信协议,编程过程比较复杂。
  2. 基于URL的高层次网编程。URL采用HTTP和HTTPS这些属于高层次的通信协议,相对低层编程过程比较容易。

所谓低层次网络编程并不等于它功能不强大。恰恰相反,正因为层次低,Socket编程与基于URL的高层次网络编程比较,能够提供更强大的功能和更灵活的控制,但是要更复杂一些。

22.3 UDP Socket低层次网络编程

UDP(用户数据报协议)就像日常生活中的邮件投递,是不能保证可靠地寄到目的地。UDP是无连接的,对系统资源的要求较少,UDP可能丢包不保证数据顺序。但是对于网络游戏和在线视频等要求传输快、实时性高、质量可稍差一点的数据传输,UDP还是非常不错的。

UDP Socket网络编程比TCP Socket编程简单多,UDP是无连接协议,不需要像TCP一样监听端口,建立连接,然后才能进行通信。

22.3.3 案例:文件上传工具

使用UDP Socket将之前我们的文件上传工具重新实现一下。

案例服务器端UploadServer 代码如下:

package com.dingjiaxiong

import java.io.BufferedOutputStream
import java.io.FileOutputStream
import java.net.DatagramPacket
import java.net.DatagramSocket


fun main() {

    println("服务端运行...")
    DatagramSocket(8080).use { socket ->
        FileOutputStream("D:\\DingJiaxiong\\IdeaProjects\\KotlinStudy\\chapter22\\src\\com\\dingjiaxiong\\TestDir\\subDir\\udpupload.jpg").use { fout ->
            BufferedOutputStream(fout).use { out ->

                // 准备一个缓冲区
                val buffer = ByteArray(1024)

                // 循环接收数据报包
                while (true) {

                    // 创建数据报包对象, 用来接收数据
                    val packet = DatagramPacket(buffer, buffer.size)
                    // 接收数据报包
                    socket.receive(packet)
                    // 接收数据长度
                    val len = packet.length

                    if (len == 3) {
                        // 获得结束标志
                        val flag = String(buffer, 0, 3)
                        // 判断结束标志, 如果是bye结束接收
                        if (flag == "bye") {
                            break
                        }
                    }

                    // 写入数据到文件输出流
                    out.write(buffer, 0, len)
                }

                println("接收完成!")
            }
        }
    }
}

与TCP Socket不同UDP Socket 无法知道哪些数据包已经是最后一个了,因此需要发送方发出一个特殊的数据包,包中包含了一些特殊标志。

再看看案例客户端UploadClient代码如下:

package com.dingjiaxiong

import java.io.BufferedInputStream
import java.io.FileInputStream
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress

fun main() {

    println("客户端运行...")
    DatagramSocket().use { socket ->
        FileInputStream("D:\\DingJiaxiong\\IdeaProjects\\KotlinStudy\\chapter22\\src\\com\\dingjiaxiong\\TestDir\\test.jpg").use { fin ->
            BufferedInputStream(fin).use { input ->

                // 创建远程主机IP地址对象
                val address = InetAddress.getByName("localhost")

                // 准备一个缓冲区
                val buffer = ByteArray(1024)
                // 首次从文件流中读取数据
                var len = input.read(buffer)

                while (len != -1) {
                    // 创建数据报包对象
                    val packet = DatagramPacket(buffer, len, address, 8080)

                    // 发送数据报包
                    socket.send(packet)

                    // 再次从文件流中读取数据
                    len = input.read(buffer)
                }

                // 创建数据报对象
                val packet = DatagramPacket("bye".toByteArray(), 3, address, 8080)

                // 发送结束标志
                socket.send(packet)
                println("上传完成!")
            }
        }
    }
}

先运行起来服务端

在这里插入图片描述

运行上传客户端

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

没毛病。上述是上传文件客户端,发送数据不会堵塞线程,因此没有使用子线程。这个结束标志是字符串bye,服务器端接收到这个字符串则结束接收数据包。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

祝我天天开心,平安健康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值