Kotlin网络编程(4)UDP Socket 低层次网络编程

  • DatagramSocket 类
  • DatagramPacket 类
  • 案例:文件上传工具

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

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

一、DatagramSocket 类

  java.net 包中提供了两个类 DatagramSocketDatagramPacker,用来支持 UDP 通信。DatagramSocket 用于在程序之间建立传送数据报的通信连接。

下面是 DatagramSocket 常用的构造函数:

  • DatagramSocket()。创建数据报 DatagramSocket 对象,并将其绑定到本地主机上任何可以的端口。
  • DatagramSocket(port: Int)。创建数据报 DatagramSocket 对象,并将其绑定到本地主机上的指定端口。
  • DatagramSocket(port: Int, laddr: InetAddress!)。创建数据报 DatagramSocket 对象,并将其绑定到指定的本地地址。

DatagramSocket 其他的常用函数和属性有:

  • send(p: DatagramPacket!)。发送数据报包。
  • receive(p: DatagramPacket!)。接收数据报包。
  • port 属性。返回 DatagramSocket 连接到的远程端口。
  • localPort。返回 DatagramSocket 绑定到的本地端口。
  • inetAddress 属性:返回 DatagramSocket 连接地址。
  • localAddress 属性:返回 DatagramSocket 绑定的本地地址。
  • isClosed 属性:判断返回 DatagramSocket 是否处于关闭状态。
  • isConnected 属性:判断返回 DatagramSocket 是否处于连接状态。
  • close() 函数:关闭 DatagramSocket。

  DatagramSocket 也实现了 AutoCloseable 接口,可以通过自动资源管理技术关闭 DatagramSocket。

二、DatagramPacket 类

  DatagramPacket 用来表示数据报包,是数据传输的载体。

下面是 DatagramPacket 的构造函数:

  • DatagramPacket(buf: ByteArray!, length: Int)。构造数据报包,其中 buf 是包数据,length 是接收包数据的长度。
  • DatagramPacket(buf: ByteArray!, length: Int, address: InetAddress!, port: Int)。构造数据报包,包发送到指定主机上的指定端口号。
  • DatagramPacket(buf: ByteArray!, offset: Int, length: Int)。构造数据报包,其中 offset 是 buf 字节数组的偏移量。
  • DatagramPacket(buf: ByteArray!, offset: Int, length: Int, address: InetAddress!, port: Int)。构造数据报包,包发送到指定主机上的指定端口号。

DatagramPacket 常用属性如下:

  • address。返回发往或接收该数据报包相关的主机 IP 地址,属性类型是 InetAddress。
  • data。返回数据报包中的数据,属性类型是 ByteArray。
  • length。返回发送或接收到数据的长度,属性类型是 Int。
  • offset。返回发送或接收到的数据的偏移量,属性类型是 Int。
  • port。返回发送或接收该数据报包相关的主机的端口号,属性类型是 Int。

三、案例:文件上传工具

  • 案例服务器端 UploadServer 代码:
fun main(args: Array) {
    println("服务器端运行...")
    startServer()
}

fun startServer() {
    DatagramSocket(8080).use { socket ->
        FileOutputStream("./TestDir/subDir/src.zip").use { fos ->
            BufferedOutputStream(fos).use { bos ->
                // 准备一个缓冲区
                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
                        }
                    }

                    // 写入数据到文件输出流
                    bos.write(buffer, 0, len)
                }
                println("接收完成!")
            }
        }
    }
}

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

  • 案例客户端 UploadClient 代码:
fun main(args: Array) {
    println("客户端运行...")
    startClient()
}

fun startClient() {
    DatagramSocket().use { socket ->
        FileInputStream("./TestDir/src.zip").use { fis ->
            BufferedInputStream(fis).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("上传完成!")
            }
        }
    }
}

你可能感兴趣的:(Kotlin网络编程(4)UDP Socket 低层次网络编程)