网络编程(二):TCP socket api => ServerSocket & Socket

目录

1. TCP socket api

1.1 ServerSocket

1.1.1 构造方法

1.1.2 方法 - accept / close

1.2 Socket

1.2.1 构造方法

1.2.2 方法 - getInputStream / getOutputStream

2. TCP 回显 客户端 - 服务器

2.1 TCP 回显服务器

2.1.1 给服务器指定固定的端口号

2.1.2  建立和客户端的连接

2.1.3 对字节流对象进行包装 

2.1.4 接收请求, 计算响应, 返回响应

2.1.4.1 刷新缓冲区

2.2 TCP 回显客户端

2.2.1 TCP 内部保存对端信息

2.1.3 对字节流对象进行包装

 2.1.4 发送请求, 读取响应

 2.3 注意事项

2.3.1 服务器的 Socket 和客户端的 Socket

2.3.2 PrintWriter 的缓冲行为

 2.3.3 使用 PrintWriter 的 println 发送信息

2.3.4 服务器端 Socket 的生命周期

2.3.5 通过线程池同时处理多个客户端连接

2.4 TcpEchoServer 代码

2.5 TcpEchoClient 代码


1. TCP socket api

在上篇博客中, 我们提到, TCP 协议与 UDP 协议的差别很大, 于是操作系统提供了两套 socket api 分别供这两个协议使用.

TCP 协议的特点是:

  1. 有连接
  2. 面向字节流
  3. 全双工
  4. 可靠传输

这篇博客, 就来聊一聊和 TCP 相关的 socket api.

1.1 ServerSocket

ServerSocket 是专门供 TCP 服务器端 使用的 api.

1.1.1 构造方法

  • 和 UDP 服务器端一样, 创建 TCP 服务器端时, 也需要指定一个固定的端口号.

1.1.2 方法 - accept / close

我们知道, TCP 是 "有连接" 的, 而 ServerSocket 中的 accept 方法就是用来和客户端建立连接:

  • 当有客户端发起连接时, accept 用来接收客户端的连接

 这里的 accept 可以理解为 "接通电话":

主动打电话的那一方是客户端, 而服务器想要对客户端做出响应, 就必须先 "接通电话", accept 的作用就可以理解为是 "接通电话".

close 方法则是关闭文件资源.

1.2 Socket

Socket 是用来建立 TCP 客户端 的 api. 

但是, 在服务器端中, 也会使用 Socket (服务器的 accept 方法返回的就是 Socket 对象, 其中保存了客户端的信息, 并可以对客户端进行相关的交互操作).

也就是说, Socket 在 服务器端和客户端都会使用.

  • 服务器端和客户端, 就是通过 Socket 来保存对端的信息, 并进行通信的.

1.2.1 构造方法

TCP 具有 "有连接" 的特性, 所以会在底层保存对端的信息(IP地址和端口), 不需要我们手动创建变量来记录服务器地址, 直接在构造方法中传入即可(TCP 内部自己记住了).

1.2.2 方法 - getInputStream / getOutputStream

TCP 是面向字节流.

所以在 TCP 中, 并不是通过 receive 和 send 来进行通信的, 而是通过 getxxx() 来拿到 "字节流对象" , 通过流对象的方式来进行通信(读和写数据)的.


2. TCP 回显 客户端 - 服务器

2.1 TCP 回显服务器

2.1.1 给服务器指定固定的端口号

  1. 创建 TCP 服务器, 使用 ServerSocket
  2. 和 UDP 服务器一样, 对于服务器, 需要指定固定的端口号

2.1.2  建立和客户端的连接

TCP 服务器中, 和客户端进行通信的大前提是, 先和客户端建立起连接:

  • 当客户端发起连接时, 服务器端要进行接收, 否则后续无法进行通信

使用 accept 方法来接收客户端发起的连接.

accept 返回的是一个 Socket 对象, 后续服务器就通过这个 Socket 对象来和客户端进行通信.(这个 Socket 对象中包含了对端的信息).

这里需要注意 TCP 服务器中, ServerSocket 对象 和 Socket 对象 的区别:

  1. ServerSocket 是用来创建 TCP 服务器的 (外场的作用)
  2. Socket 的对象是 accept 的返回值, 这个对象在底层和对端的 TCP 建立起了连接, 可以和对端进行通信 (所谓连接, 就是保存了对端的信息) (内场的作用)

2.1.3 对字节流对象进行包装 

上文说到, TCP 上是通过字节流对象来进行通信的, 要想读写请求或者响应, 那就需要先拿到字节流对象:

但是, 为了方便我们进行请求响应的读写, 我们可以对这两个字节流对象进行 "包装" :

  1. 使用 Scanner 对 InputStream 进行包装: 直接读到字符串(服务器读取请求时 / 客户端读取响应时)
  2. 使用 PrintWriter 对 OutputStream 进行包装: 直接写回字符串(服务器返回响应时 / 客户端发送请求时)

经过 Scanner 和 PrintWriter 的包装后, 就不需要以字节为单位进行通信了, 可以直接以字符串的形式来进行通信.

我们之前使用 Scanner 时, 传入的是 System.in , 其实传入的 in 就是一个 InputStream 对象:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值