【ElasticSearch】ES案例:旅游酒店搜索

news2024/9/23 9:33:59

文章目录

  • 一、项目分析
  • 二、需求1:酒店搜索功能
  • 三、需求2:添加过滤功能
  • 四、需求3:我附近的酒店
  • 五、需求4:置顶花广告费的酒店

一、项目分析

启动hotel-demo项目,访问localhost:servicePort,即可访问static下的index.html:

在这里插入图片描述

从页面分析,我们需要实现搜索、分页、排序等功能。点击页面,可以看到list接口的传参为:

在这里插入图片描述

二、需求1:酒店搜索功能

接下来实现酒店搜索功能,完成关键字搜索和分页。

  • 定义接参的Dto类
@Data
public class RequestParam {

    private String key;

    private Integer page;  //pageNum

    private Integer size;  //pageSize

    private String sortBy;
}


  • 定义返回的结果类
@AllArgsConstructor
@NoArgsConstructor
@Data
public class PageResult {

    private Long total;

    private List<HotelDoc>  hotelDocList;
}
  • 定义controller接口,接收页面请求
@RestController
@RequestMapping("/hotel")
public class HotelSearchController {

    @Resource
    IHotelService hotelService;

    @PostMapping("/list")
    public PageResult searchHotel(@RequestBody RequestParam requestParam){
        return hotelService.search(requestParam);
    }

}
  • Service层要用到JavaRestHighLevelClient对象,在启动类中定义这个Bean
@SpringBootApplication
public class HotelDemoApplication {

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

    @Bean
    public RestHighLevelClient client(){
        return new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://10.4.130.220:9200")
        ));
    }

}
  • 完成Service层,利用match查询实现根据关键字搜索酒店信息
public interface IHotelService extends IService<Hotel> {
    PageResult search(RequestParam requestParam);
}
@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {

    @Resource
    RestHighLevelClient client;  //注入客户端操作的bean

    @Override
    public PageResult search(RequestParam requestParam) {
        try {
            SearchRequest request = new SearchRequest("hotel");
            //搜索关键字
            String key = requestParam.getKey();
            if (StringUtils.isNotEmpty(key)) {   //有key就走全文检索
                request.source().query(QueryBuilders.matchQuery("all", key));
            } else {   //没key就走查所有
                request.source().query(QueryBuilders.matchAllQuery());
            }
            //分页
            request.source().from((requestParam.getPage() - 1) * requestParam.getSize())    //(pageNum-1)*pageSize
                    .size(requestParam.getSize());
                    //发送请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            //处理响应结果
            return handleResponse(response);
        } catch (IOException e) {
            throw new RuntimeException();
        }

    }
	
	//处理响应结果的方法
    private PageResult handleResponse(SearchResponse response) {
        SearchHits searchHits = response.getHits();
        long total = searchHits.getTotalHits().value;
        SearchHit[] hits = searchHits.getHits();
        //Stream流将hits中的每条数据都转为HotelDoc对象
        List<HotelDoc> hotelDocList = Arrays.stream(hits).map(t -> {
            String json = t.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            return hotelDoc;
        }).collect(Collectors.toList());
        return new PageResult(total, hotelDocList);
    }
}

重启服务,搜索和分页已实现。

在这里插入图片描述

三、需求2:添加过滤功能

接下来添加品牌、城市、星级、价格的过滤功能。这里参与搜索的条件对应着不同的搜索类型,有全文检索,有精确查找,自然要用复合查询Boolean Search

在这里插入图片描述

  • 修改接参dto类:
@Data
public class RequestParam {

    private String key;

    private Integer page;  //pageNum

    private Integer size;  //pageSize

    private String sortBy;

	private String brand;  
	  
	private String starName; 
	   
	private String city;    
	
	private Integer minPrice;    
	
	private Integer maxPrice;

}
  • 修改Service层实现,这里把搜索条件的构建单独抽取成方法,一来方便后面复用,二来让代码看着清爽点
@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {

    @Resource
    RestHighLevelClient client;

    @Override
    public PageResult search(RequestParam requestParam) {
        try {
            //准备request
            SearchRequest request = new SearchRequest("hotel");
            //构建查询条件
            buildBasicQuery(requestParam, request);
            //分页
            request.source().from((requestParam.getPage() - 1) * requestParam.getSize())
                    .size(requestParam.getSize());
            //发送请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            //处理响应结果
            return handleResponse(response);
        } catch (IOException e) {
            throw new RuntimeException();
        }

    }

    private void buildBasicQuery(RequestParam requestParam, SearchRequest request) {
        BoolQueryBuilder booleanQuery = QueryBuilders.boolQuery();
        //关键字
        String key = requestParam.getKey();
        if (! isEmpty(key)) {
            booleanQuery.must(QueryBuilders.matchQuery("all", key));
        } else {
            booleanQuery.must(QueryBuilders.matchAllQuery());
        }
        //城市
        if (! isEmpty(requestParam.getCity())) {
            booleanQuery.filter(QueryBuilders.termQuery("city", requestParam.getCity()));
        }
        //品牌
        if (! isEmpty(requestParam.getBrand())) {
            booleanQuery.filter(QueryBuilders.termQuery("brand", requestParam.getBrand()));
        }
        //星级
        if (! isEmpty(requestParam.getStarName())) {
            booleanQuery.filter(QueryBuilders.termQuery("startName", requestParam.getStarName()));
        }
        //价格
        if (requestParam.getMaxPrice() != null && requestParam.getMinPrice() != null) {
            booleanQuery.filter(QueryBuilders.rangeQuery("price")
                    .lte(requestParam.getMaxPrice())
                    .gte(requestParam.getMinPrice()));
        }
        request.source().query(booleanQuery);


    }

    private static boolean isEmpty(String str){
        return str == null || "".equals(str);
    }
}

在这里插入图片描述

四、需求3:我附近的酒店

前端页面点击定位后,会将你所在的位置发送到后台:
在这里插入图片描述
接下来实现根据这个坐标,将酒店结果按照到这个点的距离升序排序。
在这里插入图片描述

距离排序与普通字段排序有所差异,对比如下:

在这里插入图片描述

开始实现需求:

  • 修改RequestParams参数,接收location字段
@Data
public class RequestParam {

    private String key;

    private Integer page;  //pageNum

    private Integer size;  //pageSize

    private String sortBy;

	private String brand;  
	  
	private String starName; 
	   
	private String city;    
	
	private Integer minPrice;    
	
	private Integer maxPrice;

	private String location;  //经纬度位置
}
  • 修改Service中,在分页前加排序逻辑
@Override
public PageResult search(RequestParam requestParam) {
    try {
        //准备request
        SearchRequest request = new SearchRequest("hotel");
        //构建查询条件
        buildBasicQuery(requestParam, request);
        //排序
        String myLocation = requestParam.getLocation();
        if(! isEmpty(myLocation)){
            request.source().sort(SortBuilders
                    .geoDistanceSort("location",new GeoPoint(myLocation))
                    .order(SortOrder.ASC)
                    .unit(DistanceUnit.KILOMETERS));
        }
        //分页
        request.source().from((requestParam.getPage() - 1) * requestParam.getSize())
                .size(requestParam.getSize());
        //发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //处理响应结果
        return handleResponse(response);
    } catch (IOException e) {
        throw new RuntimeException();
    }

}

但此时发现返回结果中少了距离你xxx千米的信息:

在这里插入图片描述

查看DSL返回结果,看到距离是在sort字段中:

在这里插入图片描述

因此需要修改结果处理的方法,且最后pageResult中是HotelDoc对象的集合,因此,修改Hoteldoc类,加distance距离字段:

@Data
@NoArgsConstructor
public class HotelDoc {
    private Long id;
    private String name;
    private String address;
    private Integer price;
    private Integer score;
    private String brand;
    private String city;
    private String starName;
    private String business;
    private String location;
    private String pic;
    //距离
    private Object distance;   //新加字段

    public HotelDoc(Hotel hotel) {
        this.id = hotel.getId();
        this.name = hotel.getName();
        this.address = hotel.getAddress();
        this.price = hotel.getPrice();
        this.score = hotel.getScore();
        this.brand = hotel.getBrand();
        this.city = hotel.getCity();
        this.starName = hotel.getStarName();
        this.business = hotel.getBusiness();
        this.location = hotel.getLatitude() + ", " + hotel.getLongitude();
        this.pic = hotel.getPic();
    }
}
private PageResult handleResponse(SearchResponse response) {
    SearchHits searchHits = response.getHits();
    long total = searchHits.getTotalHits().value;
    SearchHit[] hits = searchHits.getHits();
    List<HotelDoc> hotelDocList = Arrays.stream(hits).map(t -> {
        String json = t.getSourceAsString();
        HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
        //开始加入距离
        Object[] sortValues = t.getSortValues();   //排序字段可能不止一个
        if(sortValues.length > 0 ){
            Object sortValue = sortValues[0];
            hotelDoc.setDistance(sortValue); 拿到sort值赋值给距离
        }
        return hotelDoc;
    }).collect(Collectors.toList());
    return new PageResult(total, hotelDocList);
}

到此,需求实现:

在这里插入图片描述

五、需求4:置顶花广告费的酒店

实现让指定的酒店在搜索结果中排名置顶:

在这里插入图片描述
实现思路为:

  • HotelDoc类添加标记字段isAD,Boolean类型
  • 对于出广告费的酒店,isAD为true,前端可用这个字段给酒店打广告标签
  • 使用function score给花钱的酒店人为增加权重,干涉排序

代码实现:

  • hotelDoc类:
@Data
@NoArgsConstructor
public class HotelDoc {
    private Long id;
    private String name;
    private String address;
    private Integer price;
    private Integer score;
    private String brand;
    private String city;
    private String starName;
    private String business;
    private String location;
    private String pic;
    //距离
    private Object distance;   //新加字段
	//是否有广告费
	private Boolean isAD;
  • 更新ES数据,模拟某酒店出广告费

在这里插入图片描述

  • 加入function score算分认为控制,给isAD为true的加权
private void buildBasicQuery(RequestParam requestParam, SearchRequest request) {
    //BoolQuery原始查询条件,原始算分
    BoolQueryBuilder booleanQuery = QueryBuilders.boolQuery();
    //关键字
    String key = requestParam.getKey();
    if (!isEmpty(key)) {
        booleanQuery.must(QueryBuilders.matchQuery("all", key));
    } else {
        booleanQuery.must(QueryBuilders.matchAllQuery());
    }
    //城市
    if (!isEmpty(requestParam.getCity())) {
        booleanQuery.filter(QueryBuilders.termQuery("city", requestParam.getCity()));
    }
    //品牌
    if (!isEmpty(requestParam.getBrand())) {
        booleanQuery.filter(QueryBuilders.termQuery("brand", requestParam.getBrand()));
    }
    //星级
    if (!isEmpty(requestParam.getStarName())) {
        booleanQuery.filter(QueryBuilders.termQuery("startName", requestParam.getStarName()));
    }
    //价格
    if (requestParam.getMaxPrice() != null && requestParam.getMinPrice() != null) {
        booleanQuery.filter(QueryBuilders.rangeQuery("price")
                .lte(requestParam.getMaxPrice())
                .gte(requestParam.getMinPrice()));
    }
    
    //function score算分控制
    FunctionScoreQueryBuilder functionScoreQuery = QueryBuilders.functionScoreQuery(
            booleanQuery,  //第一个参数传入booleanQuery为原始查询,对应原始的相关性算分
            new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{  //第二个形参,function score数组,里面有个function score元素
                    new FunctionScoreQueryBuilder.FilterFunctionBuilder(  //function score元素对象,第一个参数传入筛选字段
                            QueryBuilders.termQuery("isAD", true),   //不再用酒店品牌筛选,而是isAD字段
                            ScoreFunctionBuilders.weightFactorFunction(10)  //算分函数,用默认的乘法,权重为10
                    )
            });
    request.source().query(functionScoreQuery);


}

实现效果;

在这里插入图片描述


Function Score查询可以控制文档的相关性算分,使用方式如下:

在这里插入图片描述

最后贴上以上四个需求Service层代码:

import cn.itcast.hotel.domain.dto.RequestParam;
import cn.itcast.hotel.domain.pojo.HotelDoc;
import cn.itcast.hotel.domain.vo.PageResult;
import cn.itcast.hotel.mapper.HotelMapper;
import cn.itcast.hotel.domain.pojo.Hotel;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {

    @Resource
    RestHighLevelClient client;

    @Override
    public PageResult search(RequestParam requestParam) {
        try {
            //准备request
            SearchRequest request = new SearchRequest("hotel");
            //构建查询条件
            buildBasicQuery(requestParam, request);
            //排序
            String myLocation = requestParam.getLocation();
            if (!isEmpty(myLocation)) {
                request.source().sort(SortBuilders
                        .geoDistanceSort("location", new GeoPoint(myLocation))
                        .order(SortOrder.ASC)
                        .unit(DistanceUnit.KILOMETERS));
            }
            //分页
            request.source().from((requestParam.getPage() - 1) * requestParam.getSize())
                    .size(requestParam.getSize());
            //发送请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            //处理响应结果
            return handleResponse(response);
        } catch (IOException e) {
            throw new RuntimeException();
        }

    }

    private void buildBasicQuery(RequestParam requestParam, SearchRequest request) {
        //BoolQuery原始查询条件,原始算分
        BoolQueryBuilder booleanQuery = QueryBuilders.boolQuery();
        //关键字
        String key = requestParam.getKey();
        if (!isEmpty(key)) {
            booleanQuery.must(QueryBuilders.matchQuery("all", key));
        } else {
            booleanQuery.must(QueryBuilders.matchAllQuery());
        }
        //城市
        if (!isEmpty(requestParam.getCity())) {
            booleanQuery.filter(QueryBuilders.termQuery("city", requestParam.getCity()));
        }
        //品牌
        if (!isEmpty(requestParam.getBrand())) {
            booleanQuery.filter(QueryBuilders.termQuery("brand", requestParam.getBrand()));
        }
        //星级
        if (!isEmpty(requestParam.getStarName())) {
            booleanQuery.filter(QueryBuilders.termQuery("startName", requestParam.getStarName()));
        }
        //价格
        if (requestParam.getMaxPrice() != null && requestParam.getMinPrice() != null) {
            booleanQuery.filter(QueryBuilders.rangeQuery("price")
                    .lte(requestParam.getMaxPrice())
                    .gte(requestParam.getMinPrice()));
        }

        //function score算分控制
        FunctionScoreQueryBuilder functionScoreQuery = QueryBuilders.functionScoreQuery(
                booleanQuery,  //第一个参数传入booleanQuery为原始查询,对应原始的相关性算分
                new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{  //第二个形参,function score数组,里面有个function score元素
                        new FunctionScoreQueryBuilder.FilterFunctionBuilder(  //function score元素对象,第一个参数传入筛选字段
                                QueryBuilders.termQuery("isAD", true),   //不再用酒店品牌筛选,而是isAD字段
                                ScoreFunctionBuilders.weightFactorFunction(10)  //算分函数,用默认的乘法,权重为10
                        )
                });
        request.source().query(functionScoreQuery);


    }

    private PageResult handleResponse(SearchResponse response) {
        SearchHits searchHits = response.getHits();
        long total = searchHits.getTotalHits().value;
        SearchHit[] hits = searchHits.getHits();
        List<HotelDoc> hotelDocList = Arrays.stream(hits).map(t -> {
            String json = t.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            //开始加入距离
            Object[] sortValues = t.getSortValues();
            if (sortValues.length > 0) {
                Object sortValue = sortValues[0];
                hotelDoc.setDistance(sortValue);
            }
            return hotelDoc;
        }).collect(Collectors.toList());
        return new PageResult(total, hotelDocList);
    }

    private static boolean isEmpty(String str) {
        return str == null || "".equals(str);
    }
}

最后,页面上其他地方的需求实现思路:

排序:

在这里插入图片描述
前端会传递sortBy参数,就是排序方式,后端需要判断sortBy值是什么:

  • default:相关度算分排序,这个不用管,es的默认排序策略
  • score:根据酒店的score字段排序,也就是用户评价,降序
  • price:根据酒店的price字段排序,就是价格,升序
高亮:

在这里插入图片描述

request.source()
        .query(QueryBuilders.matchQuery("all",requestParam.getKey()))
        .highlighter(new HighlightBuilder().field("name")
                .requireFieldMatch(false)
                .preTags("<strong>")
                .postTags("</strong")
        );

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/732550.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

不停服迭代更新-服务网格

系列文章目录 本章将根据多年经验&#xff0c;进行规划讲解 文章目录 系列文章目录前言一、如何做到 不停服更新、 不停服更新的机制有什么好处&#xff0c; 前言 服务迭代发版、少不了的就是停服更新&#xff0c;为了不影响 用户体验&#xff0c;大部分公司选择半夜更新迭代&…

TPCE260PCIE转PMC载板

TPCE60是一个标准的高度PCI Express版本1.1兼容的模块&#xff0c;提供了一个槽用于安装标准PMC模块&#xff0c;灵活和成本有效的I/O解决方案的各种应用如过程控制、医疗系统、电信和交通控制。 桥接PCI Express x1连接到主机板和PCI总线信号的PMC槽之间是由透明的PCIe到PCI桥…

正确释放vector的内存:clear还是swap?

一、size()和capacity()方法的区别 1、vector有size()和capacity()方法都用来获取vector的大小&#xff0c;那么它们两之间有什么区别呢&#xff1f; 我们先来看一段代码&#xff1a; int main() {std::vector<int> v1;std::cout <<"size:"<< v…

工厂模式(工厂方法和简单工厂模式)

工厂模式 概述常见分类简单工厂模式概述设计图解创建People抽象类(产品说明书)创建子类(产品角色)创建工厂(用于根据需求实例化对象)消费者简单工厂模式优点简单工厂模式缺点 工厂方法模式概述设计图解创建抽象父类(产品说明书)子类&#xff08;产品角色&#xff09;工厂工厂接…

数据结构二叉树(OJ)题

分析&#xff1a; 2. 我们要想办法区分&#xff0c;从队列当中出队的数据是属于那一层的数据 3. 我们当前这一道题的时间复杂度是O&#xff08;h * N&#xff09; h是树的高度&#xff0c;我们最坏情况就是在树的最底下找到&#xff0c;得递归h次&#xff0c;树的高度&#x…

vue开发:vue的插槽功能讲解

vue的插槽 举一个生活中的例子&#xff1a;比如装修房子的时候我们会在很多地方预留出一些插孔&#xff0c;可能要插电冰箱&#xff0c;插电式&#xff0c;插充电器等&#xff0c;反正就是你觉得预留在这个位置的插座一定有用&#xff0c;这个预留的插座就类似我们今天要说的插…

【C语言13】结构体的声明,定义与结构体的内存对齐

文章目录 一、结构体1.1结构体是什么1.2结构体声明1.3结构体的内存 以上便是结构体的介绍&#xff0c;如有不足&#xff0c;请多多指正&#xff01; 一、结构体 1.1结构体是什么 通俗的说&#xff0c;结构体就是一个类的集合&#xff0c;如同整形数组是整形数字的集合体&…

高数中的驻点以及要注意的事项

在高等数学中&#xff0c;驻点是指函数导数为零的点&#xff0c;即函数的极值点或拐点。在求解函数的最大值、最小值或拐点时&#xff0c;需要找到函数的驻点。 要注意以下几点&#xff1a; 1. 导数为零不一定是驻点&#xff1a;虽然驻点定义为函数导数为零的点&#xff0c;但…

力扣 | 双指针技巧

前文回顾&#xff1a;力扣 | 数组和字符串简介 力扣LeetBook&#xff1a;数组和字符串 文章目录 &#x1f4da;双指针技巧&#xff1a;情形一&#x1f449;反转字符串&#x1f449;数组拆分I&#x1f449;两数之和 II - 输入有序数组 &#x1f4da;双指针技巧&#xff1a;情形二…

基于智能手机的医院服务客户端设计与实现(论文+源码)_kaic

摘 要 近年来&#xff0c;随着中国经济的迅猛发展&#xff0c;医疗技术水平也在不断提高&#xff0c;但由于人口数目巨大&#xff0c;导致医疗资源人均分配不足的情况依旧十分严峻。预约挂号一直是制约医疗机构服务质量提高的主要环节之一。在传统预约挂号方式下&#xff0c;繁…

EMQ X(3):客户端websocket消息收发

在EMQ X Broker提供的 Dashboard 中 TOOLS 导航下的 Websocket 页面提供了一个简易但有效的WebSocket 客户端工具&#xff0c;它包含了连接、订阅和发布功能&#xff0c;同时还能查看自己发送和接收的报文数据&#xff0c;我们期望 它可以帮助您快速地完成某些场景或功能的测试…

ncm格式如何转换为mp3,分享几个方法!

你是否曾在网易云音乐上下载了一些NCM格式的音频文件&#xff0c;但发现无法在其他设备上播放&#xff1f;别担心&#xff0c;记灵在线工具可以帮助你将这些NCM格式转换为常见的MP3格式。今天小编就来分享三种方法&#xff0c;教你如何搞定&#xff01; 方法一&#xff1a;曲线…

C#学习之路-循环

有的时候&#xff0c;可能需要多次执行同一块代码。一般情况下&#xff0c;语句是顺序执行的&#xff1a;函数中的第一个语句先执行&#xff0c;接着是第二个语句&#xff0c;依此类推。 编程语言提供了允许更为复杂的执行路径的多种控制结构。 循环语句允许我们多次执行一个…

Notepad++设置查看函数列表的快捷键

Notepad是一个非常精巧、启动便捷、支持文本自动补全的记事本软件&#xff0c;到2023年7月&#xff0c;已经更新到了v8.5.4版本&#xff0c;这里介绍设置其查看函数列表的快捷键方法。老版本的Notepad&#xff0c;比如Notepad v7.3, 默认查看函数列表的快捷键的为F8&#xff0c…

python PYQT5 键盘,鼠标,绘制,焦点,改变,输入法,事件的方法和使用例子

https://img-blog.csdnimg.cn/7630017d3ee444eab9bdedf8d48d575f.png from PyQt5.Qt import * import sys class MyQwidget(QWidget):def __init__(self):super().__init__()def showEvent(self, a0) -> None:print("窗口被展示出来",a0)def closeEvent(self,a0) …

网络编程4——传输层TCP协议的三大安全机制:三次握手四次挥手+确认应答机制+超时重传机制

文章目录 前言一、TCP协议段与机制TCP协议的特点TCP报头结构TCP协议的机制与特性 二、TCP协议的 连接管理机制 TCP建立连接&#xff1a;三次握手 TCP断开连接&#xff1a;四次挥手 三、TCP协议的 确认应答机制 四、TCP协议的 超时重传机制 总结 前言 本人是一个刚刚上路的I…

快速入门QT大法

QT大法 个人博客地址&#xff1a;https://zjxweb.github.io/#/ 1. 入门介绍 1.1 版本控制工具 svn vss git 1.2 QT 优点 跨平台接口接单&#xff0c;容易上手一定程度上简化了内存回收 2. 创建第一个QT程序 2.1 流程 点击创建项目后&#xff0c;选择项目路径以及给项目…

计算机体系结构基础知识介绍之指令集并行的基本编译器技术(循环展开、基本管道调度)

一、基本管道调度和循环展开 为了保持管道满载&#xff0c;必须通过查找可以在管道中重叠的不相关指令序列来利用指令之间的并行性。 为了避免流水线停顿&#xff0c;相关指令的执行必须与源指令分开一定的时钟周期距离&#xff0c;该距离等于该源指令的流水线延迟。 编译器执…

linux内核TCP/IP源码浅析

目录 数据接收流程图硬件层网络层ip_rcvip_rcv_coreip_rcv_finish 和 ip_rcv_finish_coreip_local_deliverip_local_deliver_finish 和 ip_protocol_deliver_rcu 传输层tcp_v4_rcvtcp_v4_do_rcvtcp_rcv_state_processtcp_rcv_establishedtcp_recvmsg 数据结构socketsocksock_co…

允许Traceroute探测漏洞和ICMP timestamp请求响应漏洞解决方法(三)

目录 服务器检测出了漏洞需要修改 1.允许Traceroute探测漏洞解决方法 2、ICMP timestamp请求响应漏洞 服务器检测出了漏洞需要修改 1.允许Traceroute探测漏洞解决方法 详细描述 本插件使用Traceroute探测来获取扫描器与远程主机之间的路由信息。攻击者也可以利用这些信息来…