目录
📕 引言
TCP服务器与客户端的搭建需要借助以下API
TCP之间通信通过流进行传输,无论是服务器还是客户端:读取内容用输入流,写入内容用输出流
TCP 传输的是字节流,就是传输字节,传输的基本但是就是byte,所以不需要想udp那样创建一个udp数据报进行传输。
🌴ServerSocket API
ServerSocket 是创建TCP服务器Socket的API。
ServerSocket 构造方法:
ServerSocket 方法:
🎄Socket API
Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。
不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。
Socket 构造方法:
Socket 方法:
🎍建立TCP回显客户端与服务器
🚩TCP搭建服务器
我们分为以下几步来实现:
-
创建TcpEchoServer类来表示我们的服务器,并创建ServerSocket对象,初始值为null
-
在TcpEchoServer的构造方法里进行ServerSocket对象的实例化
-
用一个start()方法表示启动程序
-
在该方法内我们首先要使用accept()处理客户端发来的连接,并用Socket对象进行接收
-
我们再用一个processConnection(Socket clientSocket)方法处理我们的连接
- 使用Scanner读取数据
在读取之间做一个判断,判断是否能读取到下一个内容,能读就继续,读取不到说明TCP连接已经断开了
- 根据请求计算响应
- 把响应写回给客户端
- 服务器日志打印
整体代码:
🚩TCP搭建客户端
搭建客户端我们也可以分为以下几步:
-
创建TcpEchoClient类表示我们的客户端,创建Soket对象用于与客户端通信·
-
再TcpEchoClient构造方法里进行实例化Socket的对象
-
创建start()方法用于我们的操作
- 从控制台读取数据
- 把请求发送给服务器
- 从服务器读取到响应,把响应显示到控制台上
整体代码:
运行:
服务器启动: 客户端启动:
客户端启动之后的服务器: 客户端停止后的服务器:
启动服务器,客户端发送数据:
🚩多个客户端对一个服务器
上述代码呢,感觉好像能跑起来,但是呢还存在严重的问题!!!
1. 在服务器代码这边,对于accept创建的socket对象,是没有进行关闭操作的
- 当我们processConnection方法执行完成之后,就需要关闭了,直接加上finally即可。
- 还可以对Socket clientSocket = serverSocket.accept 。但是这里不太合适(原因下面讲述)
2. 当前代码服务器是无法给多个客户端提供服务
演示:我们启动了三个客户端,但是服务器里面只有一个客户端上线
数据发送:
- 第一个客户端发送数据,有响应
- 第二个客户端发送数据,无响应
- 第三个客户端发送数据,无响应
- 服务器只收到了第一个客户端发来的请求,没有收到第二个和第三个客户端发来的请求
- 当我们把第一个客户端停止后,服务器就能立即感知到第二个客户端上线,以及感知到第二个客户端之前发出的请求,并且立即返回响应
代码:如果代码这样写,while下面的try就不能这样写,如果这样写当我们start之后,clientSocket就立即关闭了,而process里面的clientSocket可能还正在用,所以还是使用上述的finally。
修改:
整体代码:只是修改了服务器的代码,客户端代码上述已展示,不在展示。
启动服务器客户端:
发送数据:
发送之后服务器:
第一个客户端停止后,也不影响其他客户端进行数据发送。
使用线程池解决:
🚩 拓展(IO多路复用/IO多路转接)
上述代码解决了多个客户端与一个服务器通信的问题,但是呢,在实际应用中,要是客户端太多,且客户端都不退出通信,这时候服务器被占满了,后续就无法处理个更多客户端。
这时候呢,有两种解决方法:
- 增加服务器的数量
但是呢,这种方法虽然好,但是缺点是需要钱来购买服务器
- 所以我们一般采用另一种更省钱的做法,这时候操作系统就提供了一种API,也就是IO多路复用/IO多路转接
简单理解就是客户端在进行IO操作时可能有很多的空闲时间,这时候该线程处于空闲的状态,这时候就可以让该线程去做一些其他的操作,等空闲时间一过,又立即回来继续执行。
这样即省钱,又可以容纳更多的客户端进行通信。这里只是扩展一下,就不做过多叙述了。