WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议

本文介绍Maven自动化构建工具的使用,包括Maven Wrapper的下载与配置过程,以及如何利用Maven进行项目依赖管理和构建。涵盖Maven的官方文档、Spring Boot Maven插件指南、创建OCI镜像等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它允许服务器和客户端之间进行实时的数据交换,使得网页应用能够实现类似桌面应用的即时交互功能。与传统的 HTTP 请求/响应模式不同,WebSocket 提供了一个持久的连接,使得数据可以在任何时候从服务器发送到客户端,而无需等待客户端请求。

WebSocket 的主要特点包括:

  1. 全双工通信:支持双向数据传输,即服务器可以主动向客户端推送消息。
  2. 低延迟:由于建立了持久连接,减少了建立连接的开销,从而降低了通信延迟。
  3. 高并发性:一个 WebSocket 连接可以处理多个消息,适合需要频繁通信的场景。
  4. 跨域支持:通过适当的配置,WebSocket 可以支持跨域请求,但需要注意浏览器的安全策略。

WebSocket 的使用场景非常广泛,包括但不限于:

  • 实时聊天应用
  • 在线游戏
  • 实时金融行情更新
  • 协作编辑工具
  • 实时通知系统

以下是一个简单的 WebSocket 示例代码:

服务端 (Node.js)

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function connection(ws) {
  ws.on('message', function incoming(message) {
    console.log('received: %s', message);
  });

  ws.send('something');
});

客户端 (HTML + JavaScript)

<!DOCTYPE html>
<html>
<head>
  <title>WebSocket Test</title>
</head>
<body>
  <script>
    var ws = new WebSocket('ws://localhost:8080');
    ws.onopen = function() {
      console.log('Connected to server');
    };
    ws.onmessage = function(event) {
      console.log('Received: ', event.data);
    };
  </script>
</body>
</html>

WebSocket 和 HTTP 轮询是两种不同的实时通信技术,它们在实现方式、性能和适用场景上有明显的区别。

  1. 连接类型

    • WebSocket:WebSocket 是一种持久的双向连接,一旦建立连接,服务器和客户端可以通过同一个 TCP 连接进行全双工通信。这意味着数据可以在任意时刻从客户端发送到服务器,反之亦然,而不需要重新建立连接。
    • HTTP 轮询:HTTP 轮询是一种基于 HTTP 请求的单向通信方式。客户端定时向服务器发送 HTTP 请求以获取最新数据,每次请求都是独立的,并且需要重新建立连接。
  2. 性能

    • WebSocket:由于 WebSocket 保持一个持续的连接,减少了频繁建立和关闭连接的开销,因此在实时性要求高的应用中表现更好。延迟较低,数据传输效率更高。
    • HTTP 轮询:HTTP 轮询需要频繁地发送请求,这会导致较高的网络流量和服务器负载。此外,每次轮询都有一定的延迟,因此不适合对实时性要求非常高的场景。
  3. 资源消耗

    • WebSocket:WebSocket 连接一旦建立,资源消耗相对稳定,不会因为频繁的连接和断开导致额外的开销。
    • HTTP 轮询:HTTP 轮询会频繁地创建和销毁连接,增加了服务器的资源消耗,尤其是在高并发的情况下,这种开销会更加明显。
  4. 适用场景

    • WebSocket:适用于需要高实时性的应用场景,如在线游戏、实时聊天、金融行情等。
    • HTTP 轮询:适用于对实时性要求不高的场景,或者在不支持 WebSocket 的环境中作为替代方案使用。
  5. 兼容性

    • WebSocket:现代浏览器对 WebSocket 的支持较好,但在一些老旧的浏览器中可能需要 polyfill 或降级处理。
    • HTTP 轮询:几乎所有的浏览器都支持 HTTP 请求,因此兼容性更好,但需要考虑性能问题。

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它的主要优点包括:

  1. 低延迟:WebSocket 允许服务器和客户端之间进行实时双向通信,减少了传统 HTTP 请求/响应模式中的延迟。
  2. 节省带宽:由于 WebSocket 保持一个持续的连接,避免了频繁的握手和建立连接的过程,从而节省了带宽。
  3. 简化开发:WebSocket 提供了一个简单的 API,使得开发者可以更容易地实现实时通信功能,而不需要处理底层的 TCP 连接细节。
  4. 高并发支持:WebSocket 能够高效地处理大量并发连接,适合需要实时数据推送的应用,如在线游戏、金融行情等。
  5. 跨平台兼容性:WebSocket 得到了广泛的浏览器支持,并且可以在不同的操作系统和设备上使用,确保了应用的广泛可用性。

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,与传统的 HTTP 轮询相比具有以下优势:

  1. 持久连接:WebSocket 建立的是持久连接,一旦连接建立,服务器可以随时向客户端发送消息,而不需要客户端请求。这减少了延迟和不必要的网络开销。

  2. 双向通信:WebSocket 支持服务器到客户端(Server-to-Client)和客户端到服务器(Client-to-Server)的双向通信,使得实时应用更加高效。

  3. 低延迟:由于 WebSocket 保持了持久连接,避免了频繁的连接建立和关闭操作,从而显著降低了通信延迟。

  4. 资源利用:相比于传统的 HTTP 轮询,WebSocket 减少了多次请求带来的带宽和服务器资源的浪费,因为只需要一个持续的连接来处理所有通信。

  5. 简化开发:WebSocket 提供了简单的 API,使得开发者可以更容易地实现实时通信功能,而不必处理复杂的轮询逻辑。

  6. 更好的控制:WebSocket 允许更精细的控制,例如可以设置心跳检测机制来确保连接的稳定性,以及通过帧分片传输大数据。
    WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,适用于需要实时数据传输和双向通信的应用场景。以下是一些常见的 WebSocket 适用场景:

  7. 实时聊天应用:WebSocket 可以实现即时通讯功能,用户之间可以实时发送和接收消息,无需刷新页面。

  8. 在线游戏:用于实时同步玩家的状态和游戏数据,减少延迟,提高用户体验。

  9. 实时金融行情:股票、期货等金融市场的数据变化频繁,WebSocket 可以实时推送最新的行情数据到客户端。

  10. 实时通知系统:如社交媒体的通知、邮件提醒等,通过 WebSocket 可以及时将新信息推送给用户。

  11. 远程控制:例如远程桌面、智能家居控制等,通过 WebSocket 实现对设备的实时控制和状态监控。

  12. 协作工具:如在线文档编辑、白板工具等,多个用户可以同时对同一个文档进行编辑,WebSocket 保证数据的实时同步。

  13. 直播流媒体:在视频直播或音频直播中,WebSocket 可以用于传输实时的音视频数据。

  14. 物联网(IoT)应用:设备与服务器之间的实时数据交换,如传感器数据上报、远程控制指令下发等。

  15. 实时数据分析:用于大数据处理中的实时分析,将分析结果实时反馈给前端展示。

  16. 在线客服系统:客户与客服人员之间的实时交流,提升客户服务体验。

WebSocket 和 HTTP 是两种不同的网络协议,它们在功能和使用场景上存在显著差异。以下是 WebSocket 与 HTTP 的主要区别:

  1. 连接方式

    • HTTP:每次请求都需要建立一个新的 TCP 连接,完成请求后立即断开连接。这种方式被称为“无状态”的通信模式。
    • WebSocket:一旦建立了一个 WebSocket 连接,这个连接会一直保持打开状态,允许服务器和客户端之间进行双向通信。这种持续的连接使得实时数据交换更加高效。
  2. 通信模式

    • HTTP:基于请求/响应模型,客户端发送请求到服务器,服务器处理请求并返回响应。每个请求都是独立的,没有持久的连接。
    • WebSocket:基于事件驱动的模型,允许服务器主动向客户端推送消息,而不需要等待客户端的请求。这种机制特别适合需要实时更新的应用,如在线聊天、股票行情等。
  3. 数据传输效率

    • HTTP:由于每次请求都需要建立和关闭连接,传输效率相对较低。此外,HTTP 头信息较大,增加了不必要的开销。
    • WebSocket:一旦连接建立,后续的数据包只需要很小的头部信息,减少了传输的开销,提高了数据传输的效率。
  4. 适用场景

    • HTTP:适用于传统的网页浏览、文件下载等场景,这些场景通常不需要频繁的双向通信。
    • WebSocket:适用于需要实时交互的应用,如在线游戏、实时聊天、金融交易系统等。
  5. 资源占用

    • HTTP:由于每次请求都需要建立新的连接,频繁的请求会导致较高的资源消耗。
    • WebSocket:通过保持长连接,减少了频繁建立和关闭连接的资源开销,适合高并发的场景。
  6. 安全性

    • HTTP:可以通过 HTTPS 来保证数据传输的安全性,但每次请求都需要重新建立加密通道。
    • WebSocket:可以在初始握手时使用 HTTPS 来保证连接的安全性,之后的数据通信则通过已建立的安全通道进行。

总结来说,WebSocket 提供了一种高效的双向通信机制,适合需要实时数据交换的应用;而 HTTP 更适合传统的请求/响应模式,适用于大多数静态内容的传输。

Getting Started

Reference Documentation

For further reference, please consider the following sections:

Guides

The following guides illustrate how to use some features concretely:

/*
 * Copyright 2007-present the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;

public class MavenWrapperDownloader {

    private static final String WRAPPER_VERSION = "0.5.6";
    /**
     * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
     */
    private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
        + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";

    /**
     * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
     * use instead of the default one.
     */
    private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
            ".mvn/wrapper/maven-wrapper.properties";

    /**
     * Path where the maven-wrapper.jar will be saved to.
     */
    private static final String MAVEN_WRAPPER_JAR_PATH =
            ".mvn/wrapper/maven-wrapper.jar";

    /**
     * Name of the property which should be used to override the default download url for the wrapper.
     */
    private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";

    public static void main(String args[]) {
        System.out.println("- Downloader started");
        File baseDirectory = new File(args[0]);
        System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());

        // If the maven-wrapper.properties exists, read it and check if it contains a custom
        // wrapperUrl parameter.
        File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
        String url = DEFAULT_DOWNLOAD_URL;
        if(mavenWrapperPropertyFile.exists()) {
            FileInputStream mavenWrapperPropertyFileInputStream = null;
            try {
                mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
                Properties mavenWrapperProperties = new Properties();
                mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
                url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
            } catch (IOException e) {
                System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
            } finally {
                try {
                    if(mavenWrapperPropertyFileInputStream != null) {
                        mavenWrapperPropertyFileInputStream.close();
                    }
                } catch (IOException e) {
                    // Ignore ...
                }
            }
        }
        System.out.println("- Downloading from: " + url);

        File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
        if(!outputFile.getParentFile().exists()) {
            if(!outputFile.getParentFile().mkdirs()) {
                System.out.println(
                        "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
            }
        }
        System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
        try {
            downloadFileFromURL(url, outputFile);
            System.out.println("Done");
            System.exit(0);
        } catch (Throwable e) {
            System.out.println("- Error downloading");
            e.printStackTrace();
            System.exit(1);
        }
    }

    private static void downloadFileFromURL(String urlString, File destination) throws Exception {
        if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
            String username = System.getenv("MVNW_USERNAME");
            char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
            Authenticator.setDefault(new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
        }
        URL website = new URL(urlString);
        ReadableByteChannel rbc;
        rbc = Channels.newChannel(website.openStream());
        FileOutputStream fos = new FileOutputStream(destination);
        fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
        fos.close();
        rbc.close();
    }

}

distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-activemq</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-amqp</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-artemis</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-integration</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-websocket</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.kafka</groupId>
			<artifactId>kafka-streams</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.kafka</groupId>
			<artifactId>spring-kafka</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.amqp</groupId>
			<artifactId>spring-rabbit-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.integration</groupId>
			<artifactId>spring-integration-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.kafka</groupId>
			<artifactId>spring-kafka-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值