1       Lucene介绍

1.1   什么是Lucene

Lucene是apache下的一个开源的全文检索引擎工具包。它为软件开发人员提供一个简单易用的工具包(类库),以方便的在目标系统中实现全文检索的功能。

1.2   全文检索的应用场景

1.2.1  搜索引擎

©注意:

Lucene和搜索引擎是不同的,Lucene是一套用java或其它语言写的全文检索的工具包。它为应用程序提供了很多个api接口去调用,可以简单理解为是一套实现全文检索的类库。搜索引擎是一个全文检索系统,它是一个单独运行的软件系统。

1.2.2  站内搜索(关注)

1.3  全文检索定义

  全文检索首先将要查询的目标文档中的词提取出来,组成索引,通过查询索引达到搜索目标文档的目的。这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search

2       Lucene实现全文检索的流程

全文检索的流程分为两大部分:索引流程、搜索流程。

  • 索引流程:即采集数据à构建文档对象à分析文档(分词)à创建索引。
  • 搜索流程:即用户通过搜索界面à创建查询à执行搜索,搜索器从索引库搜索à渲染搜索结果。

3       入门程序

  3.1.1  第一步:添加jar包

入门程序只需要添加以下jar包:

  1. mysql5.1驱动包:mysql-connector-java-5.1.7-bin.jar
  2. 核心包:lucene-core-4.10.3.jar
  3. 分析器通用包:lucene-analyzers-common-4.10.3.jar
  4. 查询解析器包:lucene-queryparser-4.10.3.jar

   3.1.2  PO,DAO以及测试代码

      

 package cn.xjy.po ;

 public class Book {

     // 图书ID
private Integer id ;
// 图书名称
private String name ;
// 图书价格
private Float price ;
// 图书图片
private String pic ;
// 图书描述
private String description ; public Book() {} public Book(Integer id, String name, Float price, String pic, String description) {
super() ;
this.id = id ;
this.name = name ;
this.price = price ;
this.pic = pic ;
this.description = description ;
} public Integer getId() {
return id ;
} public void setId(Integer id) {
this.id = id ;
} public String getName() {
return name ;
} public void setName(String name) {
this.name = name ;
} public Float getPrice() {
return price ;
} public void setPrice(Float price) {
this.price = price ;
} public String getPic() {
return pic ;
} public void setPic(String pic) {
this.pic = pic ;
} public String getDescription() {
return description ;
} public void setDescription(String description) {
this.description = description ;
} @Override
public String toString() {
return "Book [id=" + id + ", name=" + name + ", price=" + price + ", pic=" + pic
+ ", description=" + description + "]" ;
} }

    

 package cn.xjy.dao ;

 import java.sql.Connection ;
import java.sql.DriverManager ;
import java.sql.PreparedStatement ;
import java.sql.ResultSet ;
import java.util.ArrayList ;
import java.util.List ;
import cn.xjy.po.Book ; public class BookDaoImpl implements BookDao { @Override
public List<Book> getBooks() {
List<Book> books = new ArrayList<Book>() ; try {
Class.forName("com.mysql.jdbc.Driver") ;
Connection con = DriverManager.getConnection("jdbc:mysql:///luncene", "root", "root") ;
PreparedStatement statement = con.prepareStatement("select * from book") ;
ResultSet resultSet = statement.executeQuery() ;
while (resultSet.next()) {
Book book = new Book(resultSet.getInt("id"), resultSet.getString("name"),
resultSet.getFloat("price"), resultSet.getString("pic"),
resultSet.getString("description")) ;
books.add(book) ;
}
} catch (Exception e) {
e.printStackTrace() ;
} return books ;
} }

 

 package cn.xjy.lucene ;

 import java.io.File ;
import java.util.ArrayList ;
import java.util.List ;
import org.apache.lucene.analysis.Analyzer ;
import org.apache.lucene.analysis.standard.StandardAnalyzer ;
import org.apache.lucene.document.Document ;
import org.apache.lucene.document.Field ;
import org.apache.lucene.document.Field.Store ;
import org.apache.lucene.document.FloatField ;
import org.apache.lucene.document.IntField ;
import org.apache.lucene.document.TextField ;
import org.apache.lucene.index.DirectoryReader ;
import org.apache.lucene.index.IndexReader ;
import org.apache.lucene.index.IndexWriter ;
import org.apache.lucene.index.IndexWriterConfig ;
import org.apache.lucene.index.Term ;
import org.apache.lucene.queryparser.classic.QueryParser ;
import org.apache.lucene.search.BooleanClause.Occur ;
import org.apache.lucene.search.BooleanQuery ;
import org.apache.lucene.search.IndexSearcher ;
import org.apache.lucene.search.NumericRangeQuery ;
import org.apache.lucene.search.Query ;
import org.apache.lucene.search.ScoreDoc ;
import org.apache.lucene.search.TermQuery ;
import org.apache.lucene.search.TopDocs ;
import org.apache.lucene.store.Directory ;
import org.apache.lucene.store.FSDirectory ;
import org.apache.lucene.util.Version ;
import org.wltea.analyzer.lucene.IKAnalyzer ;
import cn.xjy.dao.BookDao ;
import cn.xjy.dao.BookDaoImpl ;
import cn.xjy.po.Book ; public class TestLucene { /**
* 创建索引库
* @throws Exception
*/
public void lucene() throws Exception {
BookDao bookDao = new BookDaoImpl() ;
List<Book> books = bookDao.getBooks() ;
// 采集数据的目的是为了索引,在索引前需要将原始内容创建成文档(Document),
// 文档(Document)中包括一个一个的域(Field)。 // 1.创建document集合对象
List<Document> documents = new ArrayList<Document>() ; // 2.循环遍历数据集,根据需求创建不同的filed,添加到对应的document对象中
Document document = null ;
for (Book book : books) {
document = new Document() ;
Field id = new IntField("id", book.getId(), Store.YES) ;
Field name = new TextField("name", book.getName(), Store.YES) ; if (book.getId()==4)
name.setBoost(100f) ;// 设置权重.值越大搜索越靠前
Field price = new FloatField("price", book.getPrice(), Store.YES) ;
Field pic = new TextField("pic", book.getPic(), Store.YES) ;
Field description = new TextField("description", book.getDescription(), Store.NO) ; document.add(id) ;
document.add(name) ;
document.add(price) ;
document.add(pic) ;
document.add(description) ;
documents.add(document) ;
} // 3.把每个document对象添加到document集合中 // 4.分析文档,对文档中的内容记性分词,实例化分析器对象,首先创建索引目录
Analyzer analyzer = new StandardAnalyzer() ;
Directory directory = FSDirectory.open(new File("src/index")) ; // 5.创建indexWriterConfig对象
IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer) ; // 6.创建indexWriter对象
IndexWriter writer = new IndexWriter(directory, config) ; // 7.通过indexWriter对象,添加文档对象,写入索引库的过程
for (Document doc : documents) {
writer.addDocument(doc) ;
} // 8.关闭indexWriter流
writer.close() ; } /**
* 创建索引库,可解析中文
* @throws Exception
*/
public void luceneCN() throws Exception {
BookDao bookDao = new BookDaoImpl() ;
List<Book> books = bookDao.getBooks() ;
// 采集数据的目的是为了索引,在索引前需要将原始内容创建成文档(Document),
// 文档(Document)中包括一个一个的域(Field)。 // 1.创建document集合对象
List<Document> documents = new ArrayList<Document>() ; // 2.循环遍历数据集,根据需求创建不同的filed,添加到对应的document对象中
Document document = null ;
for (Book book : books) {
document = new Document() ;
Field id = new IntField("id", book.getId(), Store.YES) ;
Field name = new TextField("name", book.getName(), Store.YES) ; if (book.getId()==4)
name.setBoost(100f) ;// 设置权重.值越大搜索越靠前
Field price = new FloatField("price", book.getPrice(), Store.YES) ;
Field pic = new TextField("pic", book.getPic(), Store.YES) ;
Field description = new TextField("description", book.getDescription(), Store.YES) ; document.add(id) ;
document.add(name) ;
document.add(price) ;
document.add(pic) ;
document.add(description) ;
documents.add(document) ;
} // 3.把每个document对象添加到document集合中 // 4.分析文档,对文档中的内容记性分词,实例化分析器对象,首先创建索引目录
Analyzer analyzer = new IKAnalyzer();
Directory directory = FSDirectory.open(new File("src/index")) ; // 5.创建indexWriterConfig对象
IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer) ; // 6.创建indexWriter对象
IndexWriter writer = new IndexWriter(directory, config) ; // 7.通过indexWriter对象,添加文档对象,写入索引库的过程
for (Document doc : documents) {
writer.addDocument(doc) ;
} // 8.关闭indexWriter流
writer.close() ; } /**
* 删除指定的索引
* @throws Exception
*/
public void deleteIndex() throws Exception {
// 1.指定索引库的位置
Directory directory = FSDirectory.open(new File("src/index")) ; // 2.创建indexWriterConfig
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LATEST, null) ; // 3.创建indexWriter
IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig) ; // 4.删除指定的索引(new Term())
// indexWriter.deleteDocuments(new Term("id", "1"));//参数是Term()
// indexWriter.deleteDocuments(new QueryParser("id", new
// StandardAnalyzer()).parse("id:1"));//参数为query
indexWriter.deleteAll() ;// 删除所有
// 5.关闭流
indexWriter.close() ; System.out.println("删除成功") ; // 在查询一遍验证是否删除
searchIndex() ;
} /**
* 更新索引,
* 最好的做法是先查出要修改的索引进行更新
* @throws Exception
*/
public void updateIndex() throws Exception {
// 1.指定索引库
Directory directory = FSDirectory.open(new File("src/index")) ; // 2.定义indexReader
IndexReader indexReader = DirectoryReader.open(directory) ; // 3.定义indexSearcher
IndexSearcher indexSearcher = new IndexSearcher(indexReader) ; Query query = new QueryParser("id", new StandardAnalyzer()).parse("id:1") ;
// 查询索引库
TopDocs topDocs = indexSearcher.search(query, 1) ; // 获取查询到的对象
ScoreDoc scoreDoc = topDocs.scoreDocs[0] ; // 获取document对象
Document document = indexSearcher.doc(scoreDoc.doc) ; // 更新内容
document.removeField("name") ;
document.add(new TextField("name", "这是测试更新的内容", Store.YES)) ; // 初始化indexWriterConfig和indexWriter对象
IndexWriterConfig IndexWriterConfig = new IndexWriterConfig(Version.LATEST,
new StandardAnalyzer()) ;
IndexWriter indexWriter = new IndexWriter(directory, IndexWriterConfig) ; // 开始更新,这个方法第一个参数如果设置为null,则不会删除原来的数据,而且添加了一条更新后的新数据
// 为了保证数据的严谨性,必须删除为更新之前的数据,添加上更新后的数据就哦了
indexWriter.updateDocument(new Term("id", "1"), document) ;
indexWriter.close() ;
indexReader.close() ; System.out.println("更新成功") ;
} /**
* 可多条件连接QueryParser会将用户输入的查询表达式解析成Query对象实例。
* 搜索 Query query = queryParser.parse("*:*") ;
* @throws Exception
*/
public void searchIndex() throws Exception {
// 创建分析器
Analyzer analyzer = new StandardAnalyzer() ; // 查询条件
QueryParser queryParser = new QueryParser("description", analyzer) ;
Query query = queryParser.parse("description:个") ; // 指定搜索目录
Directory directory = FSDirectory.open(new File("src/index")) ; // 创建indexReader
IndexReader indexReader = DirectoryReader.open(directory) ; // 创建indexSearch对象
IndexSearcher indexSearcher = new IndexSearcher(indexReader) ; // 查询索引库
TopDocs topDocs = indexSearcher.search(query, 10) ; // 获取前十条记录
ScoreDoc [] scoreDocs = topDocs.scoreDocs ; System.out.println("文档个数:" + topDocs.totalHits) ; for (ScoreDoc scoreDoc : scoreDocs) {
Document doc = indexSearcher.doc(scoreDoc.doc) ;
System.out.println(doc) ;
}
} /**
* 这种不可多条件查询
* 搜索 Query query = new TermQuery(new Term("id", "1"));
* @throws Exception
*/
public void searchIndex2() throws Exception {
// 创建分析器
Analyzer analyzer = new StandardAnalyzer() ; // 查询条件
Query query = new TermQuery(new Term("description", "徐景洋驻马店")) ; // 指定搜索目录
Directory directory = FSDirectory.open(new File("src/index")) ; // 创建indexReader
IndexReader indexReader = DirectoryReader.open(directory) ; // 创建indexSearch对象
IndexSearcher indexSearcher = new IndexSearcher(indexReader) ; // 查询索引库
TopDocs topDocs = indexSearcher.search(query, 10) ; // 获取前十条记录
ScoreDoc [] scoreDocs = topDocs.scoreDocs ; System.out.println("文档个数:" + topDocs.totalHits) ; for (ScoreDoc scoreDoc : scoreDocs) {
Document doc = indexSearcher.doc(scoreDoc.doc) ;
System.out.println(doc) ;
}
} /**
* NumericRangeQuery,指定数字范围查询.(创建field类型时,注意与之对应)
* 搜索 Query query = NumericRangeQuery.newIntRange("id", 1, 9, true, true);
* @throws Exception
*/
public void searchIndex3() throws Exception {
// 创建分析器
Analyzer analyzer = new StandardAnalyzer() ; // 查询条件
// 创建查询
// 第一个参数:域名
// 第二个参数:最小值
// 第三个参数:最大值
// 第四个参数:是否包含最小值
// 第五个参数:是否包含最大值 Query query = NumericRangeQuery.newIntRange("id", 1, 9, true, true) ; // 指定搜索目录
Directory directory = FSDirectory.open(new File("src/index")) ; // 创建indexReader
IndexReader indexReader = DirectoryReader.open(directory) ; // 创建indexSearch对象
IndexSearcher indexSearcher = new IndexSearcher(indexReader) ; // 查询索引库
TopDocs topDocs = indexSearcher.search(query, 10) ; // 获取前十条记录
ScoreDoc [] scoreDocs = topDocs.scoreDocs ; System.out.println("文档个数:" + topDocs.totalHits) ; for (ScoreDoc scoreDoc : scoreDocs) {
Document doc = indexSearcher.doc(scoreDoc.doc) ;
System.out.println(doc) ;
}
} /**
* 1、MUST和MUST表示“与”的关系,即“并集”。
2、MUST和MUST_NOT前者包含后者不包含。
3、MUST_NOT和MUST_NOT没意义
4、SHOULD与MUST表示MUST,SHOULD失去意义;
5、SHOUlD与MUST_NOT相当于MUST与MUST_NOT。
6、SHOULD与SHOULD表示“或”的概念。 * BooleanQuery,布尔查询,实现组合条件查询。
* 搜索 BooleanQuery query = new BooleanQuery() ;
* @throws Exception
*/
public void searchIndex4() throws Exception {
// 创建分析器
Analyzer analyzer = new StandardAnalyzer() ; // 查询条件
BooleanQuery query = new BooleanQuery() ; Query query1 = new TermQuery(new Term("name", "spring")) ;
Query query2 = NumericRangeQuery.newFloatRange("price", 60f, 80f, true, true) ; // MUST:查询条件必须满足,相当于AND
// SHOULD:查询条件可选,相当于OR
// MUST_NOT:查询条件不能满足,相当于NOT非
query.add(query2, Occur.SHOULD) ;
query.add(query1, Occur.MUST) ; // 指定搜索目录
Directory directory = FSDirectory.open(new File("src/index")) ; // 创建indexReader
IndexReader indexReader = DirectoryReader.open(directory) ; // 创建indexSearch对象
IndexSearcher indexSearcher = new IndexSearcher(indexReader) ; // 查询索引库
TopDocs topDocs = indexSearcher.search(query, 10) ; // 获取前十条记录
ScoreDoc [] scoreDocs = topDocs.scoreDocs ; System.out.println("文档个数:" + topDocs.totalHits) ; for (ScoreDoc scoreDoc : scoreDocs) {
Document doc = indexSearcher.doc(scoreDoc.doc) ;
System.out.println(doc) ;
}
} }
 package cn.xjy.test ;

 import org.junit.Test ;
import cn.xjy.lucene.TestLucene ; public class MyTest { @Test
public void testIndex() throws Exception {
TestLucene lucene = new TestLucene() ;
// lucene.lucene();
lucene.luceneCN() ;
System.out.println("创建成功") ;
} @Test
public void testSearch() throws Exception {
TestLucene lucene = new TestLucene() ;
// lucene.searchIndex();
lucene.searchIndex2() ;
// lucene.searchIndex3();
// lucene.searchIndex4();
} @Test
public void testDelete() throws Exception {
TestLucene lucene = new TestLucene() ;
lucene.deleteIndex() ;
} @Test
public void testUpdate() throws Exception {
TestLucene lucene = new TestLucene() ;
lucene.updateIndex() ;
}
}

配置文件:IKAnalyzer.cfg.xml

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties> <comment>IK Analyzer 扩展配置</comment>
<!-- 用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">mydict.dic</entry>
<!-- 用户可以在这里配置自己的扩展停用词字典 -->
<entry key="ext_stopwords">ext_stopword.dic</entry> </properties>

4      Field域

4.1   Field属性

  Field是文档中的域,包括Field名和Field值两部分,一个文档可以包括多个Field,Document只是Field的一个承载体,Field值即为要索引的内容,也是要搜索的内容。

是否分词(tokenized)

是:作分词处理,即将Field值进行分词,分词的目的是为了索引。

比如:商品名称、商品简介等,这些内容用户要输入关键字搜索,由于搜索的内容格式大、内容多需要分词后将语汇单元索引。

否:不作分词处理

比如:商品id、订单号、身份证号等

是否索引(indexed)

是:进行索引。将Field分词后的词或整个Field值进行索引,索引的目的是为了搜索。

比如:商品名称、商品简介分析后进行索引,订单号、身份证号不用分析但也要索引,这些将来都要作为查询条件。

否:不索引。该域的内容无法搜索到

比如:商品id、文件路径、图片路径等,不用作为查询条件的不用索引。

是否存储(stored)

是:将Field值存储在文档中,存储在文档中的Field才可以从Document中获取。

比如:商品名称、订单号,凡是将来要从Document中获取的Field都要存储。

否:不存储Field值,不存储的Field无法通过Document获取

比如:商品简介,内容较大不用存储。如果要向用户展示商品简介可以从系统的关系数据库中获取商品简介。

4.2   Field常用类型

  下边列出了开发中常用 的Filed类型,注意Field的属性,根据需求选择:

  

Field类

数据类型

Analyzed

是否分词

Indexed

是否索引

Stored

是否存储

说明

StringField(FieldName, FieldValue,Store.YES))

字符串

N

Y

Y或N

这个Field用来构建一个字符串Field,但是不会进行分词,会将整个串存储在索引中,比如(订单号,身份证号等)

是否存储在文档中用Store.YES或Store.NO决定

LongField(FieldName, FieldValue,Store.YES)

Long型

Y

Y

Y或N

这个Field用来构建一个Long数字型Field,进行分词和索引,比如(价格)

是否存储在文档中用Store.YES或Store.NO决定

StoredField(FieldName, FieldValue)

重载方法,支持多种类型

N

N

Y

这个Field用来构建不同类型Field

不分析,不索引,但要Field存储在文档中

TextField(FieldName, FieldValue, Store.NO)

TextField(FieldName, reader)

字符串

Y

Y

Y或N

如果是一个Reader, lucene猜测内容比较多,会采用Unstored的策略.

5   使用中文分词器IKAnalyzer

  IKAnalyzer继承Lucene的Analyzer抽象类,使用IKAnalyzer和Lucene自带的分析器方法一样,将Analyzer测试代码改为IKAnalyzer测试中文分词效果。

如果使用中文分词器ik-analyzer,就在索引和搜索程序中使用一致的分词器ik-analyzer。

5.1 添加jar包

      

  • 代码部分在上面的部分包含有中文解析.

全文检索技术---Lucene的更多相关文章

  1. (转)全文检索技术学习(一)——Lucene的介绍

    http://blog.csdn.net/yerenyuan_pku/article/details/72582979 本文我将为大家讲解全文检索技术——Lucene,现在这个技术用到的比较多,我觉得 ...

  2. Lucene全文检索技术

    Lucene全文检索技术 今日大纲 ●    搜索的概念.搜索引擎原理.倒排索引 ●    全文索引的概念 ●    使用Lucene对索引进行CRUD操作 ●    Lucene常用API详解 ●  ...

  3. Lucene全文检索技术学习

    ---------------------------------------------------------------------------------------------------- ...

  4. ELK-全文检索技术-lucene

    ELK   :  ELK是ElasticSearch,LogStash以及Kibana三个产品的首字母缩写 一.倒排索引 学习elk,必须先掌握倒排索引思想, 参考文档: https://www.cn ...

  5. JAVAEE——Lucene基础:什么是全文检索、Lucene实现全文检索的流程、配置开发环境、索引库创建与管理

    1. 学习计划 第一天:Lucene的基础知识 1.案例分析:什么是全文检索,如何实现全文检索 2.Lucene实现全文检索的流程 a) 创建索引 b) 查询索引 3.配置开发环境 4.创建索引库 5 ...

  6. 全文搜索技术—Lucene

    1.   内容安排 实现一个文件的搜索功能,通过关键字搜索文件,凡是文件名或文件内容包括关键字的文件都需要找出来.还可以根据中文词语进程查询,并且支持多种条件查询. 本案例中的原始内容就是磁盘上的文件 ...

  7. 全文检索(Lucene&Solr)

    全文检索(Lucene&Solr) 1)什么是全文检索?为什么需要全文检索? 结构化数据(mysql等)方便查询,而非结构化数据(如多篇文章)是难以查询到自己需要的,所以要使用全文检索. 全文 ...

  8. 全文检索框架---Lucene

    一.什么是全文检索 1.数据分类 我们生活中的数据总体分为两种:结构化数据和非结构化数据.   结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等.   非结构化数据:指不定长或无固定格式 ...

  9. (转)全文检索技术学习(二)——配置Lucene的开发环境

    http://blog.csdn.net/yerenyuan_pku/article/details/72589380 Lucene下载 Lucene是开发全文检索功能的工具包,可从官方网站http: ...

随机推荐

  1. 19条ANDROID平台设计规范平台设计规范

    1.尺寸以及分辨率: Android的界面尺寸比较流行的有:480*800.720*1280.1080*1920,我们在做设计图的 时候建议是以 480*800的尺寸为标准: 2.界面基本组成元素: ...

  2. MySQL 基础数据类型优化(如何选择数据类型)

    前言:      最近在看高性能 MySQL,记录写学习笔记:           高性能 MySQL 学习笔记(二) Schema与数据类型优化      笔记核心内容:MySQL 如何选择正确的数 ...

  3. 配合Jenkins自动化构建,bat脚本(一)

    C:\Windows\System32\inetsrv\appcmd.exe stop site ServiceIIS C:\Windows\System32\inetsrv\appcmd.exe s ...

  4. Android Volley完全解析(四),带你从源码的角度理解Volley

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17656437 经过前三篇文章的学习,Volley的用法我们已经掌握的差不多了,但是 ...

  5. 现网CPU飙高,Full GC告警

    现网CPU飙高,Full GC告警 https://www.cnblogs.com/QG-whz/p/9647614.html 问题出现:现网CPU飙高,Full GC告警 CGI 服务发布到现网后, ...

  6. 滑雪(经典DP思想)

    个人心得:思想还是不够,开始自己写但是不知道如何记录长度,也不太知道状态的转移,后面看了百度, 发现人人为我我为人人就是一步一步推导, 而递归思想就要求学会记录和找到边界条件,这一题中的话就是用递归, ...

  7. 「新手向」koa2从起步到填坑

    前传 出于兴趣最近开始研究koa2,由于之前有过一些express经验,以为koa还是很好上手的,但是用起来发现还是有些地方容易懵逼,因此整理此文,希望能够帮助到一些新人. 如果你不懂javascri ...

  8. 解决count distinct多个字段的方法

    Distinct的作用是用于从指定集合中消除重复的元组,经常和count搭档工作,语法如下 COUNT( { [ ALL | DISTINCT ] expression ] | * } ) 这时,可能 ...

  9. (转载)Windows: "net use" command introduction

    1)建立空连接: net use ""IP"ipc$ "" /user:"" (一定要注意:这一行命令中包含了3个空格) 2)建立 ...

  10. 基于TCP协议 I/O多路转接(select) 的高性能回显服务器客户端模型

    服务端代码: myselect.c #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> ...