美文网首页
Kotlin网络编程(4)UDP Socket 低层次网络编程

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

作者: 狼性代码人 | 来源:发表于2019-07-03 12:46 被阅读0次
    • 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<String>) {
        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<String>) {
        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 低层次网络编程

          本文链接:https://www.haomeiwen.com/subject/zrfdcctx.html