`
leiyongping88
  • 浏览: 76898 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

zoie-3.3+lucene3.5实时检索和查询

 
阅读更多

表1.1 Lucene版本发布历史

版本

发布日期

里程碑

0.01

2000年3月30日

在SourceForge网站第一次开源发布

0.04

2000年4月19日

包含基于语法的语汇单元化StandardTokenizer等

1.0

2000年10月日

修复bug,性能优化

1.01b

2001年6月2日

在SourceForge网站最后一次发布,修复bug,支持前缀查询

1.2 rc1

2001年10月2日

在Apache Jakarta第一次发布

1.2 rc2

2001年10月19日

发布源代码,修复bug

1.2 rc3

2002年1月27日

修复bug

1.2 rc4

2002年2月14日

修复bug

1.2 rc5

2002年5月14日

新增MultiFieldQueryParser等,修复bug

1.2 rc6

2002年6月13日

修改QueryParser支持?通配符

1.3 rc1

2003年3月24日

修改QueryParser支持范围查询,修复bug

1.3 rc2

2003年10月22日

新增CachingWrapperFilter和PerFieldAnalyzerWrapper等,修复bug

1.3 rc3

2003年11月25日

支持minMergeDocs,修复bug

1.3 final

2003年12月26日

修复bug

1.4 rc1

2004年3月29日

修改.tis文件格式,新增ParallelMultiSearcher等

1.4 rc2

2004年3月30日

修复bug

1.4 rc3

2004年5月11日

修复bug

1.4 final

2004年7月1日

修复bug,更新部分API实现

1.4.1

2004年8月2日

修复bug

1.4.2

2004年10月1月

修复bug,优化IndexSearcher

1.4.3

2004年12月7日

修复bug

1.9 rc1

2006年2月21日

新增MMapDirectory等,修复bug

1.9.1 final

2006年2月27日

兼容1.4.3之后的版本,修复bug

1.9.1

2006年3月2日

修复bug

2.0.0

2006年6月1日

修复bug,性能优化,不在兼容1.4.3版本

2.1.0

2007年2月17日

新增FieldSelector等,修复bug,性能优化

2.2.0

2007年6月19日

新增BoostingTermQuery等,修复bug,性能优化

2.3.0

2008年1月23日

新增SpanQueryFilter等,修复bug,性能优化

2.3.1

2008年2月22日

修复bug

2.3.2

2008年5月6日

修复bug

2.4.0

2008年10月8日

新增QueryAutoStopWordAnalyzer等,修复bug,性能优化

2.4.1

2009年3月9日

修复bug

2.9.0

2009年9月25日

新增FieldCacheRangeFilter等,修复bug,性能优化

2.9.1

2009年11月6日

修复bug

2.9.2

2010年2月26日

修复bug,性能优化

2.9.3

2010年6月18日

修复bug,性能优化

2.9.4

2010年12月3日

修复bug,性能优化

3.0.0

2009年11月25日

新增AttributeFactory等,修复bug,性能优化

3.0.1

2010年2月26日

修复bug,性能优化

3.0.2

2010年6月18日

修复bug,性能优化

3.0.3

2010年12月3日

修复bug,性能优化

3.1.0

2011年3月31日

新增ReusableAnalyzerBase等,修复bug,性能优化

3.2.0

2011年6月3日

新增TieredMergePolicy等,修复bug,性能优化

3.3.0

2011年7月1日

新增TwoPhaseCommitTool等,修复bug,性能优化

3.4.0

2011年9月14日

新增FixedBitSet等,修复bug,性能优化

3.5.0

2011年11月27日

新增IndexSearcher.searchAfter等,修复bug,性能优化

3.6.0

2012年4月12日

新增FieldValueFilter等,修复bug,性能优化

3.6.1

2012年7月22日

修复bug,性能优化

3.6.2

2012年12月25日

修复bug

4.0.0-alpha

2012年7月3日

新增RegexpQuery等,修复bug,性能优化

4.0.0-beta

2012年8月13日

新增BloomFilteringPostingsFormat等,修复bug,性能优化

4.0.0

2012年10月12日

新增BlockPostingsFormat等,修复bug

4.1.0

2013年1月22日

新增AnalyzingSuggester和FuzzySuggester等,性能优化

4.2.0

   

4.3.0

   

4.4.0

   

zoie最新版本只支持lucene3.5 lucene3.6+目前不支持,zoie最新版本为zoie-core-3.3.0

spring配置文件:

 <bean id="userIndexJob" class="org.summercool.platform.searchengine.indexjob.UserIndexJob"
        init-method="init" destroy-method="destroy">
        <property name="zoieBatchDelay" value="120000"/>
           <property name="zoieBatchSize" value="3000"/>
           <property name="userIndexPath" value="WEB-INF/classes/dataIndex/user/"></property>
    </bean>

检索部分:

public class UserIndexJob {
    private Log log = LogFactory.getLog(UserIndexJob.class);
   
    public static final long MAX_INCREMENT_INDEX_NUMBER = 1300000; // 最大增量索引资源数
   
    public String userIndexPath;
   
    private IdCompator idCompator = new IdCompator();// id比较器
   
    private long _currentVersion = 0L;
   
    @SuppressWarnings("rawtypes")
    public ZoieSystem zoieSystem;
   
    //批量大小:即队列中放入多少项方才触发索引
    // 内存中的大小
    private  int zoieBatchSize;

    //批量延时:即等待多长时间方才触发索引
    // 最大延迟时间(单位:毫秒)
    private  int zoieBatchDelay;

    private  float docboost = 1.0f;
   
    private  int rows = 20000;
   
    public String lastUpdateTime;
   
   
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void init(){
        try {
            System.out.println("UserIndexJob init start");
            //索引文件夹
            File idxDir = new File(userIndexPath);
            if(!idxDir.exists()){
                idxDir.mkdir();
            }
            //数据解析器
            ZoieIndexableInterpreter interpreter = new MyUserInfoDataInterpreter();
            //设置翻译器
            DefaultIndexReaderDecorator decorator = new DefaultIndexReaderDecorator();
           
            PerFieldAnalyzerWrapper analyzer = new PerFieldAnalyzerWrapper(new IKAnalyzer());
            ZoieConfig zoieConfig = new ZoieConfig();
            zoieConfig.setBatchDelay(zoieBatchDelay);
            zoieConfig.setBatchSize(zoieBatchSize);
            zoieConfig.setAnalyzer(analyzer);//设置分词器
            zoieConfig.setSimilarity(new DefaultSimilarity());//设置相似性评分器
            zoieConfig.setRtIndexing(true);
            zoieSystem = new ZoieSystem(idxDir, interpreter, decorator, zoieConfig);
            zoieSystem.start();
            zoieSystem.getAdminMBean().flushToDiskIndex();
            System.out.println("UserIndexJob init end");
            setLastUpdateTime();    // 设置上次更新时间
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e, e);
        }
    }
   
   

    @SuppressWarnings("unchecked")
    public void doUpdateIndexData(){
        try {
            System.out.println("执行job start");
            // 增量索引,检查资源是否有更新
            UserInfoDao userInfoDao = ServiceFactory.getBean(UserInfoDao.class);
            String maxUpdateTime = userInfoDao.getUserLastModify();
            if (StringUtils.isNotBlank(lastUpdateTime) && lastUpdateTime.equals(maxUpdateTime)) { // 无资源更新
                System.out.println("======user index data no update!========");
                return;
            }
            Thread.sleep(1000);
            long maxId = 0;
            long total = 0;
            int start = 0;
            if (StringUtils.isNotBlank(lastUpdateTime)){// 增量索引
                // 得到增量索引量
                long increNum = userInfoDao.getIncrementIndexResNumber(lastUpdateTime, maxUpdateTime);
                if (increNum > MAX_INCREMENT_INDEX_NUMBER) { // 转换成全量索引
                    lastUpdateTime = null; // 全量索引
                }
            }
           
            if(StringUtils.isBlank(lastUpdateTime)){
                maxId = userInfoDao.getMaxID();
            }
           
            long begin = System.currentTimeMillis();
            while (true) {
                List<UserInfo> resList = userInfoDao.findUserIndexInfo(lastUpdateTime,maxUpdateTime,start, rows);
                if (resList.size() > 0) { // 索引资源
                    List<DataEvent<Document>> dataEventList = transform(resList);
                    if (null != dataEventList && !dataEventList.isEmpty()) {
                        zoieSystem.consume(dataEventList);
                    }
                }
                total += resList.size();
                System.out.println("=========user index increment num:" + total);
                if (resList.size() < rows) {
                    break;
                }
               
                if (null == lastUpdateTime) { // 全量索引
                    if (resList.size() > 0) {
                        Collections.sort(resList, idCompator); // 排序
                        if (resList.get(0).getUserId() >= maxId) { // 全量索引完成
                            break;
                        }
                    }
                }
                start = start + rows;
            }
            long end = System.currentTimeMillis();
            lastUpdateTime = maxUpdateTime;
            System.out.println("============user index increment total num:" + total
                    + ",elasped time " + ((end - begin) / 1000) + " seconds");
        } catch (Exception e) {
            e.printStackTrace();
            log.info(e.getMessage(),e);
        }
    }
   
    private List<DataEvent<Document>> transform(List<UserInfo> resList) {
        List<DataEvent<Document>> dataEventList = new ArrayList<DataEvent<Document>>();
        if (resList != null && !resList.isEmpty()) {
            for (UserInfo user : resList) {
                Document doc = new Document();
                doc.setBoost(docboost);
                doc.add(new Field("userId", user.getUserId().toString(), Field.Store.YES,Field.Index.NOT_ANALYZED));
                doc.add(new Field("headImg", StringUtils.isNotBlank(user.getHeadImg())?user.getHeadImg() : "", Field.Store.YES,Field.Index.NOT_ANALYZED));
                doc.add(new Field("nickName", StringUtils.isNotBlank(user.getNickName())?user.getNickName():"", Field.Store.YES,Field.Index.ANALYZED));
                doc.add(new Field("loginName", StringUtils.isNotBlank(user.getLoginName())?user.getLoginName():"", Field.Store.YES,Field.Index.NOT_ANALYZED));
                doc.add(new Field("checkinCount", String.valueOf(user.getCheckinCount()), Field.Store.YES,Field.Index.NOT_ANALYZED));
                doc.add(new Field("favoriteCount", String.valueOf(user.getFavoriteCount()), Field.Store.YES,Field.Index.NOT_ANALYZED));
                doc.add(new Field("sex", String.valueOf(user.getSex()), Field.Store.YES,Field.Index.NOT_ANALYZED));
                doc.add(new Field("updatedTime",  StringUtils.isNotBlank(user.getUpdatedTime())?user.getUpdatedTime():"", Field.Store.YES,Field.Index.NOT_ANALYZED));
                dataEventList.add(new DataEvent<Document>(doc, "1.0"));
            }
        }
        return dataEventList;
    }
   
   
    @SuppressWarnings("unchecked")
    private void setLastUpdateTime() {
        List<ZoieIndexReader<IndexReader>> zoieReaderList = null;
        MultiReader multiReader = null;
        IndexSearcher indexSearcher = null;
        try {
            zoieReaderList = zoieSystem.getIndexReaders();
            multiReader = new MultiReader(zoieReaderList.toArray(new IndexReader[zoieReaderList.size()]), false);
            indexSearcher = new IndexSearcher(multiReader);
            indexSearcher.setSimilarity(new AppSimilarity());
            Sort sort = new Sort(new SortField("updatedTime",SortField.STRING, true));
            TopDocs topDocs = indexSearcher.search(new MatchAllDocsQuery(), 1, sort);
            if (topDocs.totalHits == 0) {
                System.out.println("======search user index path no results======");
                return;
            }
            Document doc = indexSearcher.doc(topDocs.scoreDocs[0].doc);
            lastUpdateTime = DateUtil.formateDate(doc.get("updatedTime"), 1);
            System.out.println("lastUpdateTime:"+lastUpdateTime);
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(null !=indexSearcher){
                    indexSearcher.close();
                    indexSearcher = null;
                }
                if (null != multiReader) {
                    multiReader.close();
                    multiReader = null;
                }
                if (null != zoieReaderList && !zoieReaderList.isEmpty()) {
                    zoieSystem.returnIndexReaders(zoieReaderList);
                    zoieReaderList = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void destroy(){
        zoieSystem.shutdown(); // 将内存索引刷新到磁盘索引中
        System.out.println("destroy method");
    }

    private static class IdCompator implements Comparator<UserInfo> {
        public int compare(UserInfo o1, UserInfo o2) {
            if (o2.getUserId() > o1.getUserId()) {
                return 1;
            } else if (o2.getUserId() < o1.getUserId()) {
                return -1;
            }
            return 0;
        }
    }
   
   
    public String getZoieVersion() {
        return Long.toString(_currentVersion);
    }

    public String getMinZoieVersion() {
        return Long.toString(0L);
    }

    public String nextZoieVersion() {
        return Long.toString(++_currentVersion);
    }
   
   
    public String getUserIndexPath() {
        return userIndexPath;
    }

    public void setUserIndexPath(String userIndexPath) {
        if(StringUtils.isNotBlank(userIndexPath)){
            this.userIndexPath =SearchEngineCore.getResourcePath(userIndexPath)+ File.separator + "userIndex";
        }else{
            this.userIndexPath = SearchEngineCore.getIndexpath("VSOYOU_USER_INDEX_PATH")+ File.separator + "userIndex";
        }
    }

    @SuppressWarnings("rawtypes")
    public ZoieSystem getZoieSystem() {
        return zoieSystem;
    }

    @SuppressWarnings("rawtypes")
    public void setZoieSystem(ZoieSystem zoieSystem) {
        this.zoieSystem = zoieSystem;
    }

    public int getZoieBatchSize() {
        return zoieBatchSize;
    }

    public void setZoieBatchSize(int zoieBatchSize) {
        this.zoieBatchSize = zoieBatchSize;
    }

    public int getZoieBatchDelay() {
        return zoieBatchDelay;
    }

    public void setZoieBatchDelay(int zoieBatchDelay) {
        this.zoieBatchDelay = zoieBatchDelay;
    }
}

 

 

 

实时搜索部分:

public class UserSearch {
    private UserIndexJob userIndexJob;

    @SuppressWarnings("unchecked")
    public Map<String, Object> seachUser(String searchWord, int page, int pageSize) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put(Const.HEADIMG_DOMAIN_KEY,Const.HEADIMG_DOMAIN_VALUE);
        List<ZoieIndexReader<IndexReader>> zoieReaderList = null;
        MultiReader multiReader = null;
        IndexSearcher indexSearcher = null;
        TopDocs topDocs = null;
        try {
            searchWord = SearchUtil.wmlEncode(searchWord);
            searchWord = SearchUtil.traditionalToSimple(searchWord).trim();// 繁体转简体
           
            zoieReaderList = userIndexJob.zoieSystem.getIndexReaders();
            multiReader = new MultiReader(zoieReaderList.toArray(new IndexReader[zoieReaderList.size()]), false);
            indexSearcher = new IndexSearcher(multiReader);
            indexSearcher.setSimilarity(new DefaultSimilarity());
           
            BooleanQuery allQuery = new BooleanQuery();
            QueryParser parser = new QueryParser(Version.LUCENE_35,"nickName",new IKAnalyzer());
            Query query = parser.parse(searchWord);
            query.setBoost(100.0f);
            allQuery.add(query, BooleanClause.Occur.SHOULD);
           
            QuerySort keywordQuerySort = getKeywordQuerySort(searchWord);
            keywordQuerySort.query.setBoost(50.0f);
            allQuery.add(keywordQuerySort.query, BooleanClause.Occur.SHOULD);
           
            topDocs = indexSearcher.search(allQuery, page*pageSize, keywordQuerySort.sort);
            if(topDocs == null || topDocs.totalHits ==0){
                map.put("list", null);
                return map;
            }
            map.put("pageCount", getPageCount(topDocs.totalHits,pageSize));
            ScoreDoc[] scoreDocs = topDocs.scoreDocs; // 搜索返回的结果集合
            //查询起始记录位置
            int begin = (page - 1)*pageSize ;
            //查询终止记录位置
            int end = Math.min(begin + pageSize, scoreDocs.length);
            List<UserInfo> userInfos = addHits2List(indexSearcher,scoreDocs,begin,end);
            map.put("list", userInfos);
           
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (null != indexSearcher) {
                    indexSearcher.close();
                    indexSearcher = null;
                }
                if (null != multiReader) {
                    multiReader.close();
                    multiReader = null;
                }
                if (null != zoieReaderList && !zoieReaderList.isEmpty()) {
                    userIndexJob.zoieSystem.returnIndexReaders(zoieReaderList);
                    zoieReaderList = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return map;
       
    }
   
    private static List<UserInfo> addHits2List(IndexSearcher indexSearcher,ScoreDoc[] scoreDocs, int begin, int end) {
        List<UserInfo> userInfos = new ArrayList<UserInfo>();
        try {
            for (int i = begin; i < end; i++) {
                int docID = scoreDocs[i].doc;
                Document doc = indexSearcher.doc(docID);
                UserInfo userInfo = new UserInfo();
                userInfo.setCheckinCount(Integer.valueOf(doc.get("checkinCount")));
                userInfo.setFavoriteCount(Integer.valueOf(doc.get("favoriteCount")));
                userInfo.setHeadImg(doc.get("headImg"));
               
                if(StringUtils.isNotBlank(doc.get("nickName"))){
                    userInfo.setNickName(doc.get("nickName"));
                }else{
                    userInfo.setNickName(doc.get("loginName"));
                }
                userInfo.setLoginName(doc.get("loginName"));
                userInfo.setSex(Integer.valueOf(doc.get("sex")));
                userInfo.setUserId(Long.valueOf(doc.get("userId")));
                userInfos.add(userInfo);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return userInfos;
    }
   
    private static QuerySort getKeywordQuerySort(String searchWord) {
        QuerySort querySort = new QuerySort();
        querySort.query = new PrefixQuery(new Term("loginName", searchWord));
       
        //先按记录的得分排序,然后再按记录的签到总数倒序,收藏总数倒序
        querySort.sort = new Sort(new SortField[] {
                new SortField(null,SortField.SCORE,false),
                new SortField("checkinCount", SortField.INT, true),
                new SortField("favoriteCount", SortField.INT, true)
            });
        return querySort;
    }


    private int getPageCount(int rowCount, int pageSize) {
        int pageCount = 1;
        if ((rowCount % pageSize) == 0) {
            pageCount = rowCount / pageSize;
        } else {
            pageCount = rowCount / pageSize + 1;
        }
        if (pageCount == 0) {
            pageCount = 1;
        }
        return pageCount;
    }
   
    public UserIndexJob getUserIndexJob() {
        return userIndexJob;
    }


    public void setUserIndexJob(UserIndexJob userIndexJob) {
        this.userIndexJob = userIndexJob;
    }

}

分享到:
评论

相关推荐

    Lucene5学习之增量索引(Zoie)

    在信息检索领域,Lucene是一个广泛使用的全文搜索引擎库,其强大的索引能力和高效的搜索性能为开发者提供了强大的支持。然而,随着数据量的不断增长,如何高效地进行增量索引,即只对新增或更新的数据进行索引,而...

    lucene5+zoie实现近实时索引

    本篇文章将详细介绍如何利用Lucene 5和Zoie来构建一个能够实现实时或近实时索引更新的系统。 一、Lucene 5:全文搜索引擎的基石 Lucene是一款开源的Java库,它提供了高性能、可扩展的文本搜索功能。在Lucene 5版本...

    Zoie实时搜索架构

    它维护了两个索引,一个是热索引,用于处理新数据和实时查询;另一个是冷索引,用于批量查询和历史数据的访问。这种设计兼顾了实时性和稳定性,使得Zoie在处理大量并发请求时依然能保持高效的性能。 尽管Zoie的文档...

    lucene of lietu

    **Lucene 概述** Lucene 是一个高性能、全文本搜索库,由 Doug Cutting 创建并在 2001 年...开发者可以利用 Lucene 构建自己的搜索引擎,而 LinkedIn 通过支持 Bobo 和 Zoie 等项目,进一步推动了实时搜索技术的发展。

    zoie, 实时搜索/索引系统.zip

    zoie, 实时搜索/索引系统 什么是 ZoieZoie是用Java编写的实时搜索/索引系统。维基维基在以下位置可用:http://linkedin.jira.com/wiki/display/ZOIE/Home问题问题在以下位置跟踪:http://link

    zoieleung0309.github.io

    4. **响应式设计**:随着移动设备的普及,CSS媒体查询@media用于根据设备特性调整样式,确保网站在各种屏幕尺寸下都能正常显示。 5. **定位机制**:static、relative、absolute、fixed等定位方式及其应用场景,帮助...

    垂直搜索-您不知道的秘密 -solr中国-风雨V1.1

    - **Solr**、**Elasticsearch**、**Zoie**、**BoCo**等:基于Lucene开发的搜索引擎解决方案,各有特色。 - **Sphinx**:一款高性能的全文检索引擎,适用于大数据量的实时搜索。 - **Xapian**:一种高度可扩展的全文...

    吴一男:网易通用搜索优化之道

    - 搜索索引和检索引擎基于开源项目Lucene构建,而实时索引采用了Zoie技术。 - 数据接入可能利用DataStream进行同步,支持HTTP/REST API和Java SDK等多种服务接口。 - 系统配置管理使用了Zookeeper工具,以实现...

    CSDN TUP第二期:王鹏云演讲PPT

    - **Zoie**:基于Lucene构建,来自LinkedIn,适用于中小规模的实时搜索需求。 - **Sphinx**:自1.10-beta版本起支持实时搜索功能,被广泛应用于craigslist、netlog等网站。 通过以上分析可以看出,实时搜索不仅是一...

    搜索实时更新系统架构介绍.pptx

    - 在实时更新过程中,确保全量和实时数据的一致性至关重要。这可能涉及到软提交(SoftCommit)和硬提交(HardCommit),以及使用像Zoie这样的系统来管理多个索引版本。 8. **数据处理模型**: - 数据模型设计包括将...

    j2ee面试考察点.pdf

    3. **实时搜索设计**:如Zoie系统,结合内存和磁盘,提供快速的搜索响应。 4. **Lucene TF/IDF公式**:TF(Term Frequency)衡量词频,IDF(Inverse Document Frequency)衡量词的重要性,共同决定文档相关性。 5....

    ewhine_search:ewhine 搜索系统使用 zoie

    The ewhine search system use zoie. #安装 git clone :jimrok/ewhine_search.git cd ewhine_search java -jar server.jar 如果在Mac的控制台下,使用 java -Dfile.encoding=UTF-8 -jar server.jar #索引 在ewhine_...

    张琨:教育社交平台的web架构分享

    张琨分享的内容涉及了“三人行网络教育平台”的Web架构设计和实现,本文将围绕这一主题,深入讲解服务器拓扑结构、缓存系统设计、存储设计架构以及具体服务与应用的设计。 首先,总体架构的设计应考虑满足当前业务...

    zoieboyd.github.io

    这个项目可能包含了用户Zoie Boyd的个人信息、作品集、博客文章或者其他相关的内容。 【描述】"zoieboyd.github.io" 的描述没有给出具体的细节,但从一般的GitHub网页实践来看,这可能是Zoie Boyd利用GitHub Pages...

    web前端+javascript+模态框

    javascript封装一个模态框:头(标题、关闭按钮)、内容、尾(操作按钮:取消和确定)。标题可以自定义,默认值是“标题”; 内容区域可以是文本或者富文本,操作按钮可以控制显隐和显示文案; 点击操作按钮执行相...

    计算机网络 实验6-7 交换机及其VLAN的配置-协议分析-ARP协议

    (6) 分析 MAC 地址和 ARP。 2. 实验内容简要描述 (1) 产生两个 VLAN,并验证配置结果; (2) 为每个 VLAN 分配交换机成员端口; (3) 进行删除 VLAN 的操作; (4) 理解 VLAN1 为什么不能被删除。 本次实验环境包括:与...

    计算机网络 实验5 传输介质 双绞线

    实验5 传输介质 1. 实验目的 (1) 了解双绞线的结构; (2) 了解制作双绞线的标准;...(4) 采用制作直通线连通计算机和交换机,测试是否连通; (5) 采用制作交叉线连通计算机和计算机,测试是否连通。

    计算机网络 实验2 Wireshark的安装与基本操作

    实验2 Wireshark的安装与基本操作 1. 实验目的 学习 Wireshark 的基本操作,抓取和分析有线局域网的数据包,熟悉一些应用层命令和协议。

Global site tag (gtag.js) - Google Analytics