Kotlin网络编程(3)TCP Socket 低层次网络编程

  • TCP Socket 通信概念
  • TCP Socket 通信过程
  • Socket 类
  • ServerSocket 类
  • 案例:文件上传工具

  TCP 是面向连接的可靠数据传输协议。TCP 通信过程类似于打电话,电话接通后双方才能通话,在挂断电话之前,电话一直占线。TCP 接连一旦建立起来,会一直占用,知道关闭连接。此外,TCP 为了保证数据的正确性,会重发一切没有收到的数据,还会对数据内容进行验证并保证数据传输的正确顺序。因此 TCP 协议对系统资源有很高的要求。

一、TCP Socket 通信概念

  Socket 是网络上的两个程序,通过一个双向的通信连接,实现数据的交流。这个链路的一端称为一个 Socket。Socket 通常用来实现客户端和服务端的连接。Socket 是 TCP/IP 协议的一个十分流行的编程接口,一个 Socket 有一个 IP 地址和一个端口号唯一确定。一旦建立连接,Socket 还会包含本机和远程主机的 IP 地址和远端口号,Socket 是成对出现的。

二、TCP Socket 通信过程

  使用 Socket 进行 C/S 结构编程的通信过程如下:


Kotlin网络编程(3)TCP Socket 低层次网络编程_第1张图片
TCP Socket 通信过程

  服务器端监听某个端口是否有连接请求,此时服务器端程序处于阻塞状态,知道客户端向服务器端发出连接请求,服务器端接收客户端请求,服务器会应答请求并处理请求,然后将结果应答给客户端,这样就会建立连接。一旦连接建立起来,通信 Socket 可以获得输入输出流对象。借助于输入输出流对象就可以实现服务器与客户端的通信,最后不要忘记关闭 Socket 和释放一些资源(包括关闭输入输出流)。

三、Socket 类

  java.net 包为 TCP Socket 编程提供了两个核心类:SocketServerSocket,分别用来表示双向连接的客户端和服务器端。

  下面是Socket类常用的构造函数

  • Socket(address: InetAddress!, port: Int):创建 Socket 对象,并指定远程主机 IP 地址和端口号;

  • Socket(address: InetAddress!, port: Int, localAddr: InetAddress!, localPort: Int):创建 Socket 对象,并指定远程主机 IP 地址、端口号以及本机的 IP 地址 (localAddr) 和 端口号 (localPort);

  • Socket(host: String!, port: Int):创建 Socket 对象,并指定远程主机名和端口号,IP 地址为 null,null 表示回送地址,即 127.0.0.1

  • Socket(host: String!, port: Int, localAddr: InetAddress!, localPort: Int):创建 Socket 对象,并指定远程主机、端口号以及本机的 IP 地址 (localAddr) 和 端口号 (localPort)。host 为主机名,IP 地址为 null,null 表示回送地址,即 127.0.0.1

  提示:“数据类型!” 表示 “平台类型”,String! 表示 String 或 String?。什么是平台类型?

  Socket 其他的常用函数和属性如下

  • getInputStream() 函数:通过此 Socket返回输入流对象。

  • getOutputStream() 函数:通过此 Socket返回输出流对象。

  • port: Int 属性:返回 Socket连接到的远程端口。

  • localPort: Int 属性:返回 Socket绑定到本地端口。

  • inetAddress 属性:返回 Socket连接地址。

  • localAddress 属性:返回 Socket绑定的本地地址。

  • isClosed 属性:判断返回 Socket是否处于关闭状态。

  • isConnected 属性:判断返回 Socket是否处于连接状态。

  • close() 函数:关闭 Socket。

  注意:Socket 与 流所占用的资源类似,不能通过 Java 虚拟机的垃圾收集器回收,需要程序员释放。释放的方式有两种,一种是可以在 finally 代码块调用 close() 函数关闭 Socket,释放流所占用的资源。另一种是通过自动资源管理技术释放资源,SocketServerSocket 都实现了 AutoCloseable 接口,所以 kotlin 中可以使用 use 函数。

四、ServerSocket 类

  ServerSocket 类常用的构造函数

  • ServerSocket(port: Int, maxQueue: Int)。创建绑定到特定端口的服务器 Socket。maxQueue 设置连接请求的最大队列长度,入多队列满时,则拒绝该连接。默认值是 50

  • ServerSocket(port: Int)。创建绑定到特定端口的服务器 Socket。连接请求的最大队列长度是 50

  ServerSocket 其他的常用函数和属性如下

  • getInputStream() 函数:通过此 Socket返回输入流对象。

  • getOutputStream() 函数:通过此 Socket返回输出流对象。

  • isClosed 属性:判断返回 Socket是否处于关闭状态。

  • isConnected 属性:判断返回 Socket是否处于连接状态。

  • accept() 函数:侦听并接收到 Socket 的连接。此函数在建立连接之前一直是阻塞状态 。

  ServerSocket 类本身不能直接获得 I/O 流对象,而是通过 accept() 函数返回 Socket 对象,通过 Socket 对象取得 I/O 流对象,进行网络通信。另外,ServerSocket 也实现了 AutoCloseable 接口,通过自动资源管理技术关闭 ServerSocket

五、案例:文件上传工具

  • 服务器端代码:
fun main(args: Array?) {
    println("服务器端运行...")
    ServerSocket(8080).use { server ->
        server.accept().use { socket ->
            BufferedInputStream(socket.getInputStream()).use { bis ->
                FileOutputStream("./TestDir/subDir/fxy.png").use { fos ->
                    bis.copyTo(fos)
                    println("接收完成!")
                }
            }
        }
    }
}

  注意:ServerSocketaccept() 函数阻塞当前线程,所以一般会是在子线程中执行 accept() 函数。

  • 客户端代码:
fun main(args: Array?) {
    println("客户端运行...")
    Socket("127.0.0.1", 8080).use { socket ->
        BufferedOutputStream(socket.getOutputStream()).use { bos ->
            FileInputStream("./TestDir/fxy.png").use { fis ->
                fis.copyTo(bos)
                println("上传成功!")
            }
        }
    }
}

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