专栏:算法设计与应用
1.3 客户端-服务器(Client-Server)框架
网络通信
网络中的每台机器都有一个唯一的IP地址,例如156.62.1.12 也有一个更方便的字符串主机名,如cache.aut.ac.nz 特殊地址127.0.0.1或localhost为本地环回地址 网络通信分层 每一层协议都使用它下面的一种协议 大多数软件应用程序只直接利用传输层或应用层的协议
TCP对UDP
传输控制协议(TCP)
- 当需要可靠的通信时,所有的数据都被传输(否则报告错误)
- 数据接收顺序与发送顺序相同
- 以无限字节流发送的数据
- 用于HTTP、FTP等可靠的应用层协议
用户数据报协议(UDP) ?用于需要低开销(低延迟)通信 ?不保证可靠性或交货顺序 ?以有限大小的独立数据包发送和接收的数据 ?用于VOIP、RTP等低延迟应用层协议
TCP、UDP端口
两个重要的传输层协议
- 传输控制协议(TCP)
- 用户数据报协议(UDP)
- TCP和UDP都使用端口的概念
- 端口用于区分机器上哪个运行的应用程序应该接收TCP或UDP通信
- 允许一台机器上的多个应用程序同时进行联网
- 使用TCP或UDP的应用程序与另一台机器指定接收机器的IP地址(或主机名)和端口号
- 端口只是整数0,…,65535
- 它们不是任何物理的东西
- 一些端口号是保留给常见的应用程序,如7为ECHO, 13为白天,20-21为FTP, 80或8080为HTTP, 81或8181为HTTPS
Java API
- Java在java.net包中使用套接字的网络概念提供了方便的网络API
Socket 和ServerSocket 用于TCP通信,以获取InputStream 和OutputStream 用于通过TCP接收和发送数据DatagramSocket 用于UDP通信发送和接收DatagramPacket URL 可以用于HTTP/HTTPS通信
Client-Server框架
- Client-Server Framework是一种描述客户端如何与服务器通信的模式
- 架构模式描述了如何在应用程序中组织模块/类
- 客户端Client总是通过请求发起通信,服务器响应请求
- 服务器最初准备一个服务器套接字侦听端口号
- 客户端使用已知的服务器IP地址和端口号连接到服务器,服务器套接字接受连接
- 每个端(客户端和服务器端)创建一个’套接字’来处理连接上的发送和接收通信
- 多个客户端可以连接到相同的服务器套接字,每个客户端-服务器连接都有自己的套接字对
Socket
- 通常,服务器还会创建一个单独的线程来侦听每个连接上的传入通信(因为多个客户端可能同时通信)
- 客户端最终可以“关闭”自己的连接
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZOfn8p66-1632818903393)(1%203%20Client-Server%20Framework%20ebe2dedd7c3a4942805d54982145f88f/Untitled%201.png)]
Java中的TCP客户端步骤
socket = new socket (HOST_NAME, HOST_PORT);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out.println(request);
String serverResponse = in.readLine();
`out.close ();
in.close ();
socket.close();
例子:猜数字游戏
GuessClient 和GuessServer (和内部类GuessGame )演示了使用客户端-服务器框架的简单网络应用程序- 每个客户端尝试猜测一个随机数,这是由服务器为该客户端确定的
GuessClient 只知道GuessServer 的IP地址和端口号(彼此之间没有对象引用)- 本例中的通信协议:
- 一旦连接被接受,服务器开始发送一条消息“猜测m和n之间的数字(包括m和n)”
- 客户端请求一个数字猜测
- 服务器回复一个合适的消息
- 继续请求/回复,直到服务器回复“正确的猜测!”,服务器和客户端都会
- 闭该连接
- 注意线程的使用
- 服务器主线程在while循环中反复监听传入的连接请求
- 当每个客户端连接时,服务器创建一个新的线程,处理来自该客户端的读取请求并发送响应
更多的线程
- 如果服务器之间的通信不是严格的请求-应答,那么服务器可能需要每个客户端连接两个线程(以及用于服务器套接字的线程)
- 一个线程监听来自客户端的传入通信
- 向客户端发送传出通信的线程
- 同样,每个客户端可能使用两个线程
- 一个线程监听来自服务器的传入通信
- 一个线程用于向服务器发送传出通信
Further information
|