1. TIME_WAIT 和 CLOSE_WAIT 的区别
-
定义
- TIME_WAIT:是主动发起关闭连接操作的一方,在发送最后一个 ACK 确认包之后进入的状态。此状态存在的意义在于确保对端能收到最后一个 ACK 包,同时让网络中可能残留的旧数据包自然消逝,防止其干扰后续相同四元组(源 IP、源端口、目的 IP、目的端口)建立的新连接。
- CLOSE_WAIT:当被动关闭连接的一方收到对方发送的 FIN 包后,会先发送 ACK 包进行确认,随后进入 CLOSE_WAIT 状态。在此状态下,该方需要处理完剩余的数据,之后再发送 FIN 包以关闭自身这端的连接。
-
要点
- 所处角色:TIME_WAIT 是主动关闭连接方的状态,CLOSE_WAIT 是被动关闭连接方的状态。
- 作用:TIME_WAIT 保证连接可靠关闭以及避免旧数据包干扰;CLOSE_WAIT 用于处理剩余数据。
- 异常情况:大量的 TIME_WAIT 状态可能会占用系统资源,而大量的 CLOSE_WAIT 往往意味着程序存在资源未正确释放的问题。
-
应用
在高并发的网络服务场景中,如电商平台的促销活动期间,会有大量的短连接不断建立和关闭。若出现大量的 TIME_WAIT 状态,可能导致系统资源耗尽,影响服务的稳定性。此时可以通过调整系统参数(如 tcp_tw_reuse
和 tcp_tw_recycle
)来缩短 TIME_WAIT 状态的持续时间。对于 CLOSE_WAIT 问题,需要检查代码中是否存在未正确关闭连接的情况,例如在使用 Socket
进行网络通信时,要确保在合适的时机调用 close()
方法。
Java 代码示例
java
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;// 服务器端示例
public class ServerExample {public static void main(String[] args) {try (ServerSocket serverSocket = new ServerSocket(8888)) {System.out.println("Server is listening on port 8888");while (true) {try (Socket socket = serverSocket.accept()) {// 处理客户端请求System.out.println("Client connected: " + socket.getInetAddress());} catch (IOException e) {e.printStackTrace();}}} catch (IOException e) {e.printStackTrace();}}
}// 客户端示例
public class ClientExample {public static void main(String[] args) {try (Socket socket = new Socket("localhost", 8888)) {System.out.println("Connected to server");// 模拟客户端操作} catch (IOException e) {e.printStackTrace();}}
}
2. TCP 监听了 80 端口后, UDP 还能否监听 80 端口
-
定义
TCP(Transmission Control Protocol)和 UDP(User Datagram Protocol)是传输层的两种不同协议。TCP 是面向连接的、可靠的传输协议,UDP 是无连接的、不可靠的传输协议。端口号是用于标识应用程序的逻辑编号,操作系统在监听端口时,会依据协议类型来区分不同的监听请求。因此,只要协议不同,即使端口号相同,也可以同时进行监听。
-
要点
- 协议独立性:TCP 和 UDP 相互独立,操作系统能根据协议类型区分监听请求。
- 端口复用:同一端口可以被不同协议的应用程序同时监听。
-
应用
在实际开发中,一些服务器会同时监听 TCP 和 UDP 的同一端口,以提供不同类型的服务。例如,Web 服务器可能同时使用 TCP 80 端口提供 HTTP 服务,使用 UDP 80 端口提供一些实时性要求较高的轻量级服务,如实时数据推送。
Java 代码示例
java
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;// TCP 服务器监听 80 端口
class TCPServer {public static void main(String[] args) {try (ServerSocket serverSocket = new ServerSocket(80)) {