Socket 与 WebSocket 深度解析

作为后端开发者,你一定听过 Socket、WebSocket,但可能混淆二者的关系 ------ 比如 "WebSocket 是不是基于 Socket?""为什么 HTTP 需要 Filter 链,WebSocket 却不用?"。今天,我们从底层原理到实战场景,结合你关注的internalDoFilter()执行逻辑,彻底讲清 Socket 与 WebSocket 的核心区别,以及 Filter 链在不同通信模型中的应用差异。

本文适合 Java 开发、架构师,以及准备面试的同学,全程结合代码案例(包含 WebSocket Filter 适配实现),拒绝纯理论,做到 "原理 + 源码 + 落地" 三合一。

一、先搞懂:Socket 的核心本质(通信的底层基石)

1.1 Socket 是什么?

Socket(套接字)不是协议,而是操作系统提供的 "网络通信编程接口(API)",是应用层与 TCP/IP 协议族通信的中间软件抽象层。

官方定义:Socket 是对 TCP/IP 协议的封装和应用,开发者无需关注底层的三次握手、数据分包 / 粘包,只需调用 Socket API 即可实现两台主机的双向通信。

通俗比喻

Socket 就像 "电话插座"------ 两台电脑要通信,必须先插好 "插座"(建立 Socket 连接),才能通过 "电话线"(TCP/IP)传输数据;操作系统负责维护 "插座" 的连接状态,开发者只需 "拨号"(发送数据)和 "接听"(接收数据)。

1.2 Socket 的核心通信模型(TCP 为例)

TCP Socket 通信分为服务端客户端,核心流程遵循 "建立连接→数据传输→关闭连接" 的经典步骤:

1.2.1 核心流程(必记)
1.2.2 Java Socket 代码示例(TCP 通信)
java 复制代码
// 服务端(Socket)
public class TcpSocketServer {
    public static void main(String[] args) throws IOException {
        // 1. 创建ServerSocket,监听8080端口
        ServerSocket serverSocket = new ServerSocket(8080);
        System.out.println("Socket服务端启动,监听8080端口...");
        
        while (true) {
            // 2. 阻塞等待客户端连接(TCP三次握手在此完成)
            Socket socket = serverSocket.accept();
            System.out.println("新客户端连接:" + socket.getInetAddress());
            
            // 3. 处理客户端请求(单线程,实际开发用线程池)
            new Thread(() -> {
                try (InputStream is = socket.getInputStream();
                     OutputStream os = socket.getOutputStream()) {
                    // 接收客户端数据
                    byte[] buffer = new byte[1024];
                    int len = is.read(buffer);
                    String msg = new String(buffer, 0, len);
                    System.out.println("接收客户端数据:" + msg);
                    
                    // 响应客户端
                    os.write(("Socket响应:" + msg).getBytes());
                    os.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        socket.close(); // 关闭连接(TCP四次挥手)
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

// 客户端(Socket)
public class TcpSocketClient {
    public static void main(String[] args) throws IOException {
        // 1. 创建Socket,连接服务端(IP+端口)
        Socket socket = new Socket("localhost", 8080);
        
        // 2. 发送数据
        OutputStream os = socket.getOutputStream();
        os.write("Hello Socket!".getBytes());
        os.flush();
        
        // 3. 接收响应
        InputStream is = socket.getInputStream();
        byte[] buffer = new byte[1024];
        int len = is.read(buffer);
        System.out.println("接收服务端响应:" + new String(buffer, 0, len));
        
        // 4. 关闭连接
        socket.close();
    }
}

1.3 Socket 的核心特点

  1. 基于 TCP/UDP 协议:Socket 本身不规定传输层协议,可基于 TCP(可靠、面向连接)或 UDP(不可靠、无连接);
  2. 全双工通信:连接建立后,客户端和服务端可双向、同时传输数据;
  3. 底层通用:所有网络通信(HTTP、WebSocket、MQTT)最终都基于 Socket 实现;
  4. 无应用层规范:Socket 仅负责字节流传输,不规定数据格式(如 HTTP 的请求头、响应体),需开发者自行定义。
关键细节:握手阶段(HTTP 升级)

客户端发起的握手请求示例:

php 复制代码
GET /ws/chat HTTP/1.1
Host: localhost:8080
Upgrade: websocket  // 核心:请求升级为WebSocket协议
Connection: Upgrade // 核心:标识连接升级
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== // 随机密钥,用于验证
Sec-WebSocket-Version: 13 // 协议版本

服务端响应示例:

php 复制代码
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= // 密钥验证结果

握手完成后,TCP 连接不会关闭,而是升级为 WebSocket 连接,进入全双工数据传输阶段。

2.3 Java WebSocket 代码示例(Tomcat 实现)

java 复制代码
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;

/**
 * WebSocket服务端(基于JSR356标准)
 * @ServerEndpoint:标注WebSocket的访问路径
 */
@ServerEndpoint("/ws/chat")
public class ChatWebSocket {
    /**
     * 连接建立时触发(握手成功后)
     */
    @OnOpen
    public void onOpen(Session session) {
        System.out.println("WebSocket连接建立:" + session.getId());
    }

    /**
     * 接收客户端消息时触发
     */
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        System.out.println("接收客户端消息:" + message);
        // 服务端主动推送消息(核心:全双工)
        session.getBasicRemote().sendText("WebSocket响应:" + message);
    }

    /**
     * 连接关闭时触发
     */
    @OnClose
    public void onClose(Session session) {
        System.out.println("WebSocket连接关闭:" + session.getId());
    }

    /**
     * 通信异常时触发
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }
}

// 客户端(HTML/JS)
/*
<!DOCTYPE html>
<html>
<head>
    <title>WebSocket客户端</title>
</head>
<body>
<script>
    // 创建WebSocket连接(底层基于TCP Socket)
    const ws = new WebSocket("ws://localhost:8080/ws/chat");
    
    // 连接建立成功
    ws.onopen = function() {
        console.log("WebSocket连接建立");
        // 发送消息
        ws.send("Hello WebSocket!");
    };
    
    // 接收服务端消息(主动推送)
    ws.onmessage = function(event) {
        console.log("接收服务端消息:" + event.data);
    };
    
    // 连接关闭
    ws.onclose = function() {
        console.log("WebSocket连接关闭");
    };
</script>
</body>
</html>
*/

2.4 WebSocket 的核心特点

  1. 基于 TCP Socket 长连接:握手后连接持续保持,无需重复三次握手;
  2. 全双工通信:服务端可主动推送数据(如实时聊天、股票行情);
  3. 应用层规范:定义了数据帧格式(文本帧、二进制帧)、关闭帧等,无需开发者自定义;
  4. 与 HTTP 兼容:握手阶段基于 HTTP,可通过 80/443 端口传输,兼容现有网络架构(如 Nginx 反向代理);
  5. 轻量级:数据帧头部开销小(仅 2-10 字节),比 HTTP 请求头更高效。

三、Socket 与 WebSocket 的核心区别(表格对比 + 底层拆解)

维度 Socket(套接字) WebSocket(协议)
本质 操作系统提供的网络通信 API(抽象层) 基于 TCP Socket 的应用层协议(RFC6455 标准)
层级 传输层与应用层之间的抽象层 应用层(依赖 Socket 底层)
通信模型 仅提供字节流传输,无应用层规范 定义了握手、帧格式、关闭等完整规范
连接特性 可基于 TCP(长连接)或 UDP(无连接) 仅基于 TCP 长连接(握手后持续保持)
数据格式 无规范,开发者自行定义(如字节数组、字符串) 标准化帧格式(文本 / 二进制 / 关闭帧)
使用场景 所有网络通信的底层(HTTP、WebSocket、MQTT) Web 场景下的实时通信(聊天、直播、监控)
开发复杂度 高(需处理粘包、分包、协议解析) 低(框架封装了底层细节,如 JSR356)
与 HTTP 的关系 HTTP 基于 Socket 实现 握手阶段基于 HTTP,传输阶段脱离 HTTP

关键补充:WebSocket ≠ Socket

很多同学会混淆二者,核心结论:

WebSocket 是应用层协议 ,Socket 是底层通信 API;WebSocket 基于 TCP Socket 实现,但 Socket 不等于 WebSocket------ 就像 "HTTP 基于 TCP,但 TCP 不等于 HTTP"。

四、核心关联:Filter 链(internalDoFilter ())在二者中的应用差异

你提供的internalDoFilter()是 Servlet Filter 链的核心执行逻辑,其核心作用是 "在 HTTP 请求到达 Servlet 前,按顺序执行 Filter 的前置 / 后置逻辑"。但 Filter 链仅适用于 HTTP 请求,WebSocket 通信中无法直接使用,这是理解二者差异的关键。

4.1 Filter 链(internalDoFilter ())的适用场景

java 复制代码
internalDoFilter() {
    if (pos < filters.size()) {
        Filter filter = filters.get(pos);
        pos++;
        // 执行当前 Filter 的前置逻辑
        filter.doFilter(request, response, this); // 传入自身,调用下一个 Filter
    } else {
        // 所有 Filter 执行完毕,调用 Servlet 的 service 方法
    }
}

Filter 链的核心依赖:

  1. HTTP 请求 - 响应模型 :Filter 接收ServletRequest/ServletResponse,对应 HTTP 的请求和响应;
  2. Servlet 容器生命周期:Filter 由 Tomcat 等 Servlet 容器管理,仅在 HTTP 请求流转时触发;
  3. 短连接特性:每次 HTTP 请求都会触发一次 Filter 链执行,符合 "请求 - 响应" 的短连接逻辑。

4.2 WebSocket 为什么不支持 Filter 链?

  1. 通信模型不同:WebSocket 是长连接、全双工通信,无 "请求 - 响应" 的单次流转,Filter 链的 "前置 - 后置" 逻辑无法适配;
  2. 数据格式不同 :WebSocket 传输的是 "帧",而非 HTTP 的请求 / 响应对象,ServletRequest/ServletResponse无法封装 WebSocket 帧;
  3. 生命周期不同:WebSocket 连接建立后持续存在,Filter 链是单次请求触发,无法覆盖长连接的全生命周期。

4.3 实战:WebSocket 的 "Filter 替代方案"(拦截器)

虽然 WebSocket 不支持 Servlet Filter,但可通过WebSocket 拦截器(EndpointConfig.Configurator) 实现类似的拦截逻辑,替代 Filter 链的功能:

java 复制代码
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;

/**
 * WebSocket拦截器(替代Filter链)
 */
public class WebSocketInterceptor extends ServerEndpointConfig.Configurator {
    /**
     * 握手阶段拦截(对应Filter的前置逻辑)
     */
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        // 1. 权限校验(对应AuthFilter)
        String token = (String) request.getHeaders().get("token").get(0);
        if (token == null || !token.equals("admin")) {
            throw new RuntimeException("WebSocket握手失败:未授权");
        }
        // 2. 日志记录(对应LogFilter)
        System.out.println("WebSocket握手成功:" + request.getRequestURI());
        // 3. 存储自定义数据(对应Filter的request.setAttribute)
        sec.getUserProperties().put("userId", "1001");
    }
}

// 应用拦截器的WebSocket服务端
@ServerEndpoint(value = "/ws/chat", configurator = WebSocketInterceptor.class)
public class ChatWebSocketWithInterceptor {
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        // 从拦截器中获取自定义数据(替代request.getAttribute)
        String userId = (String) config.getUserProperties().get("userId");
        System.out.println("WebSocket连接建立,用户ID:" + userId);
    }

    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        // 业务逻辑:消息处理(对应Servlet的service方法)
        session.getBasicRemote().sendText("拦截器验证通过,响应:" + message);
    }
}

4.4 核心对比:Filter 链 vs WebSocket 拦截器

特性 Filter 链(internalDoFilter ()) WebSocket 拦截器
触发时机 HTTP 请求到达时 WebSocket 握手阶段 / 消息传输阶段
处理对象 ServletRequest/ServletResponse HandshakeRequest/Session/Frame
核心逻辑 前置→Servlet→后置(单次请求) 握手拦截→消息拦截→关闭拦截(长连接全生命周期)
适用协议 HTTP(短连接) WebSocket(长连接)
底层依赖 Servlet 容器 WebSocket 容器(如 Tomcat 的 WebSocket 模块)

五、面试高频考点:Socket 与 WebSocket 核心问题

5.1 WebSocket 是如何基于 Socket 实现的?

  1. WebSocket 握手阶段:客户端通过 HTTP 请求(基于 TCP Socket)发起升级请求,服务端验证后返回 101 响应;
  2. 连接升级后:TCP Socket 连接保持,双方不再传输 HTTP 数据,而是按 WebSocket 帧格式传输数据;
  3. 数据传输:基于 TCP Socket 的全双工特性,服务端可主动推送帧数据到客户端。

5.2 Filter 链(internalDoFilter ())为什么不适用于 WebSocket?

核心原因:Filter 链依赖 HTTP 的 "请求 - 响应" 模型,接收ServletRequest/ServletResponse对象;而 WebSocket 是长连接、帧传输,无单次请求的流转,也无对应的请求 / 响应对象,因此无法适配。

5.3 Socket、HTTP、WebSocket 的层级关系?

php 复制代码
应用层:HTTP、WebSocket、MQTT...
↓(基于)
传输层:TCP/UDP
↓(封装为)
Socket(操作系统API)
↓(基于)
网络层:IP

核心结论:Socket 是传输层的抽象 API,HTTP 和 WebSocket 是应用层协议,均基于 TCP Socket 实现。

六、总结:核心知识点回顾

  1. Socket 的本质:操作系统提供的网络通信 API,是所有网络通信的底层基础,无应用层规范;
  2. WebSocket 的本质:基于 TCP Socket 的应用层协议,专为 Web 长连接、全双工通信设计,解决 HTTP 的推送痛点;
  3. Filter 链的适配性internalDoFilter()仅适用于 HTTP 的 "请求 - 响应" 模型,WebSocket 需用拦截器替代,核心原因是通信模型和数据格式的差异。

掌握 Socket 与 WebSocket 的区别,不仅能应对面试,更能在项目中做出正确的技术选型(如实时聊天用 WebSocket,底层通信用 Socket),理解 Filter 链在不同协议中的应用边界。

相关推荐
ren049182 小时前
网络知识和Servlet重点
网络·servlet
野犬寒鸦3 小时前
面试常问:HTTP 1.0 VS HTTP 2.0 VS HTTP 3.0 的核心区别及底层实现逻辑
服务器·开发语言·网络·后端·面试
HalvmånEver4 小时前
Linux:初始网络(上)
linux·网络·学习·通信
Hello World . .4 小时前
Linux:网络编程-基于HTTP协议的天气预报查询系统开发详解
linux·网络·http
良许Linux4 小时前
汽车电子技术和汽车网络
网络·单片机·嵌入式硬件·汽车·嵌入式·制造
凉拌菜5 小时前
手术摄像系统的视频延迟是如何产生的?从采集到网络传输的技术解析
网络·音视频·医疗视频·4k视频·术野摄像机
Survivor0016 小时前
VMware虚拟机网络技术
linux·服务器·网络
Filotimo_6 小时前
5.1 计算机网络概述与网络硬件基础
网络
小涛不学习6 小时前
WebSocket 技术详解(原理 + 使用 + 面试总结)
websocket·网络协议·面试