澳门美高梅手机网站 WebSocket详解(六):刨根问底WebSocket与Socket的涉

正文转自:http://www.cnblogs.com/zjj2816/archive/2006/12/26/603659.html

1、前言

对于广大头接触Web端即时通讯技术之丁吧,WebSocket是只十分新的定义,但毋庸置疑它是现阶段Web端即时通讯技术被最俏的第一词。随便点开平篇稿子,只要说打算开Web端即时通讯相关的之动,老司机等推举的无一例外都是WebSocket。

那么好了,我知道当为此WebSocket,但对知其然知其所以然的码农习惯,我要待了解下面这些题目:

1)Socket 和 WebSocket 有哪些区别及沟通?

2)WebSocket 和 HTML5 是呀关系?

3)必须于浏览器中才会下 WebSocket 吗?

4)WebSocket 能跟 Socket 一样传输 raw 数据么?

5)WebSocket 和 Socket 相比会多消耗流量么?

然,目前网上全面介绍这半种协议的汉语文章并无多,或者说不够完善。我无法找到同样首稿子会缓解点的备题目。因此,我勾勒了本文,把找到的
Socket 和 WebSocket 的连锁资料做一个梳,以有利于清楚。

正文并无能够一直完整应上面提出的几乎单问题,但读了本文,要明了地方的那些问题,是老轻之从。由于能力有限,本文不可能非常丰富。而且,技术细节并非有人数犹肯仔细询问。但本文包含了汪洋底表面链接,跟随这些链接,可以找到足够多之底细,满足你/我的求知欲。Are
you ready?

攻交流:


即时通讯开发交流群:320837163[推荐]


移动端IM开发入门文章:《新手入门一首就够用:从零星支出活动端IM》

(本文同步发表让:http://www.52im.net/thread-1273-1-1.html)

初稿如下:

2、系列文章

正文是鳞次栉比文章中的第5首,本系列文章的提纲之类:

《WebSocket详解(一):初步认识WebSocket技术》

《WebSocket详解(二):技术原理、代码演示与下案例》

《WebSocket详解(三):深入WebSocket通信协议细节》

《WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)》

《WebSocket详解(五):刨根问底HTTP与WebSocket的干(下篇)》

《WebSocket详解(六):刨根问底WebSocket与Socket的涉及》(本文)

《WebSocket详解(七):WebSocket协议以及Socket.io开源工程》

 

3、更多材料

Web端即时通讯新手入门贴:

《新手入门贴:详解Web端即时通讯技术之原理》

Web端即时通讯技术盘点请参见:

《Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE》

关于Ajax短轮询:

搜索这地方的材料没什么意义,除非忽悠客户,否则要考虑任何3栽方案即可。

关于Comet技术�的详尽介绍请参见:

《Comet技术详解:基于HTTP长连接的Web端实时通信技术》

《WEB端即时通讯:HTTP长连接、长轮询(long
polling)详解》

《WEB端即时通讯:不用WebSocket也一如既往能够搞定消息之尽管时性》

《开源Comet服务器iComet:支持百万出现的Web端即时通讯�方案》

关于WebSocket的详实介绍请参见:

《新手快速入门:WebSocket简明教程》

《WebSocket详解(一):初步识WebSocket技术》

《WebSocket详解(二):技术原理、代码演示与动用案例》

《WebSocket详解(三):深入WebSocket通信协议细节》

《Socket.IO介绍:支持WebSocket、用于WEB端的即时通讯的框架》

《socket.io和websocket
之间是呀关联?有什么区别?》

关于SSE的详实介绍文章呼吁参见:

《SSE技术详解:一种植新的HTML5服务器推送事件技术》

又多WEB端即时通讯文章呼吁见:

http://www.52im.net/forum.php?mod=collection&action=view&ctid=15

话说有矣WebBrowser类,终于不用好手动封装SHDocVw的AxWebBrowser这个ActiveX控件了。这个仿佛设单纯作为一个跟IE一模一样浏览器,那就算极单调了(还非若直接用IE呢)。那么,无论我们是想做一个“定制版本IE”,还是期待使HTML来举行用户界面(指WinApp而非WebApp。许多单机软件,包括Windows的支援支持中心,都是HTML做的),都少不了Windows
Form和含在WebBrowser中之Web页面的交互。本文将通过几只实际的事例,初步介绍一下WinForm和WebBrowser所包含的Web页面之间的彼此。

4、技术对比

摘了 WebSocket
技术下,不可避免的,我只要将它和其他协商及技巧做一下比较。最广泛的,就是得比
WebSocket 与 HTTP、Socket
技术之异同。本系列文章被《WebSocket详解(四):刨根问底HTTP与WebSocket的干(上篇)》、《WebSocket详解(五):刨根问底HTTP与WebSocket的涉及(下篇)》两首详细谈论了WebSocket和HTTP的涉,那么本篇将只是谈谈WebSocket和Socket的话题。

WebSocket 是为着满足基于 Web 的长的实时通信需求要发生的。在人情的
Web 中,要贯彻实时通信(比如网页的QQ,聊天系统等),通用的主意是采取
HTTP
协议持续发送请求(按照往底技术力量一般是应用轮询、Comet技术解决)。

HTTP协议是未持久化的,单为的网络协议,在成立连接后止同意浏览器为服务器发出请求后,服务器才会返相应的数量。当用即时通讯时,通过轮询在一定的光阴距离(如1秒),由浏览器为服务器发送Request请求,然后将行的数额返回给浏览器。这样的道极其引人注目的缺点就是是急需持续的发送请求,而且一般HTTP
request的Header是蛮丰富之,为了传输一个死有些的数据
需要付巨大的代价,是坏无划算的,占用了众多底宽带。这种措施就浪费带富(HTTP
HEAD 是较大之),又吃服务器 CPU 占用(没有音信吗要是接受请求)。

▲ 轮询和WebSocket技术于网延迟上之对立统一(本图来自:websocket.org)

而是用 WebSocket 技术,则会大幅降低地方提到的消耗,如下图所出示。

▲ 轮询和WebSocket技术于多少流量消耗及之自查自纠(本图来自:websocket.org)

关于更详尽的描述,尹立的及时首文章说道得老好:《WebSocket(2)–为什么引入WebSocket商量》。

这就是说,WebSocket 到底与 Socket 又有什么联系?这就算如摆到 OSI 模型与 TCP/IP
协议族。

脚的代码假设你已经立了一个Windows
Form,上面有一个WebBrowser名为“webBrowser”。

5、OSI 模型与 TCP/IP

以下是维基百科面临关于OSI
模型的印证:

开放式系统互联通信参考模型(英语:Open System Interconnection
Reference Model,ISO/IEC 7498-1),简称为OSI模型(OSI
model),一栽概念模型,由国际标准化组织(ISO)提出,一个意欲要各种计算机在世界范围外相互连也网络的业内框架。

要是 TCP/IP 协议得以看作是针对性 OSI
模型的相同栽简化(以下内容来自维基百科):

它们将软件通信过程抽象化为四只抽象层,采取协议堆叠的不二法门,分别的作出不同通信协议。协议套组下的各种协商,依其效用不同,被分级归属到马上四独阶层中7,常让视为是简化的七层OSI模型。

此出平等布置图详细介绍了 TCP/IP 协议族中之逐条协议于 OSI模型
中的遍布,一贪图胜千言(此图高清版:点此下载):

TCP/IP 协和及 OSI
模型的情节,在互联网上发很多。我未曾必要更介绍其。在此处,我们特需要明白,HTTP、WebSocket
等协议都是地处 OSI 模型的极高层: 应用层 。而 IP
协议工作以网络层(第3重叠),TCP 商工作在传输层(第4叠)。

至于 OSI
模型的逐条层次都发生什么系统以及它对应,这里产生篇特别好之篇章可满足大家的求知欲:OSI七层模型详解。

Study Case 1:用WinForm的Event Handler响应Web页面的风波

6、WebSocket 与 TCP

自从点的觊觎中得以视,HTTP、WebSocket 等应用层协议,都是因 TCP
商事来传输数据的,我们可管这些高级协议理解成对 TCP 的卷入。

既然大家都使用 TCP 协议,那么大家之连日和断开,都设准TCP
商讨中之老三软握手和季软握手,只是于一连之后发送的情见仁见智,或者是断开的辰不一。

重新详实内容可读:《wireshark抓包图解
TCP三不好握手/四不良挥手详解》。

对 WebSocket 来说,它要靠 HTTP 协议进行相同糟糕握手
,握手成功后,数据就直从 TCP 通道传输,与 HTTP
无关了(具体可见文章《WebSocket详解(五):刨根问底HTTP与WebSocket的关联(下篇)》)。

现行发诸如此类一个Windows
Application,它的界面及就发生一个WebBrowser,显示一个本地的HTML文件作为界面。现在之问题是,所有逻辑都足以在HTML文件里,唯独“关闭”按钮遇到了艰苦——通常,Web页面是从未艺术直接控制浏览器的,更不用说罢是WinForm程序了。

7、再来八卦一下WebSocket的原由

由于绵绵,计算机方面许多政工呢为不了那么了解。但WebSocket是一个特别新的物,可以于咱们见到其是怎么样变成现在咱们来看底斯法的。

唯独,在.Net 2.0中档,“由Windows Form响应Web页面的波”已经成了切实可行。

7.1 WHATWG(Web Hypertext Application Technology Working Group)

至于HTML5的故事多总人口且是知的,w3c放弃了HTML,然后起同等丛人(也来就是这些口供职的小卖部,不过官方的文档上是说的私)创立了WHATWG组织来促进HTML语言的存续开拓进取,同时,他们还提高了很多有关Web的技术标准,这些标准不断地吃合法所承受。WebSocket就属WHATWG发布之Web
Application的同一片段(即HTML5)的产物。

当.Net
2.0惨遭,整个HTML文档以及该蕴含的相继HTML元素,都跟一个个HtmlDocument、HtmlElement之类的.Net对象对应。因此一旦找到这“关闭”按钮对应之HtmlElement对象,为其click事件添加Event
Handler即可。

7.2 为什么会发出WebSocket

约莫在08年的下,WG的工程师于讨论网络环境受到待平等栽都双工的连年形式,刚开头一直叫「TCPConnection」,并讨论了这种协议需支持之效益,大致已经同咱们今天收看的WebSocket差不多矣。他们认为基于现有的HTTP之上的局部术(如长轮询、Comet)并满足不了这种要求,有必不可少定义一个全新的商事。

假使HTML源代码如下:

7.3 名称的缘故

以群之关于HTML5或者WebSocket的文档中,都能望一个名,Hixie(Ian
Hickson),他是WHATWG组织的发言人,曾供职于Netscape、Opera、Google,看工作的营业所虽知晓是人之背景了。

▲ hixie

08年6月18日,一多WHATWG的工程师在座谈一些技艺问题,一个工程师提到说「我们之前讨论的可怜东西,不要受TCPConnection
了,还是打分别的名字吧
」,接着几个名给提及,DuplexConnection,TCPSocket,SocketConnection
,一个深受mcarter(Michael Carter
)的工程师说他这要描写一首关于Comet的篇章,如果得以确定是称呼,想以文章被引用这名字。

Socket一直以来还受人为此来代表网络中一个连的两岸,考虑到怎么吃工程师还容易接受,后来Hixie说了平等句「我看WebSocket这个名字就是杀合乎嘛(Hixie
briefly pops back online to record that “WebSocket” would probably be a
good new name for the TCPConnection
object)」,大家还没有异议,紧接着mcarter在Comet
Daily中上了稿子《Independence Day: HTML5 WebSocket Liberates Comet
From
Hacks》,后来乘各国大浏览器对WebSocket的支持,它化了事实上的正统,IETF也沿用了这个名字。

脚是当WHATWG文档中针对WebSocket接口的定义:

enum BinaryType {“blob”,”arraybuffer”};

[Constructor(USVString url, optional (DOMString or sequence)
protocols = []), Exposed=(Window,Worker)]

interface WebSocket : EventTarget {

readonly attribute USVString url;

// ready state

const unsigned short CONNECTING = 0;

const unsigned short OPEN = 1;

const unsigned short CLOSING = 2;

const unsigned short CLOSED = 3;

readonly attribute unsigned short readyState;

readonly attribute unsigned long long bufferedAmount;

// networking

attribute EventHandler onopen;

attribute EventHandler onerror;

attribute EventHandler onclose;

readonly attribute DOMString extensions;

readonly attribute DOMString protocol;

void close([Clamp] optional unsigned short code, optional USVString
reason);

// messaging

attribute EventHandler onmessage;

attribute BinaryType binaryType;

void send(USVString data);

void send(Blob data);

void send(ArrayBuffer data);

void send(ArrayBufferView data);

};

<html>
<body>
<input type=”button” id=”btnClose” value=”关闭” />
</body>
</html>

8、再来看望Socket

Socket可以生出诸多意,和IT较相关的原意大致是赖当端到端的一个连续着,这有限单端叫做Socket。对于IT从业者来说,它数借助的凡TCP/IP网络环境受到之星星点点个连接端,大多数之API提供者(如操作系统,JDK)往往会提供基于这种概念的接口,所以对开发者来说吧一再是当说一样栽编程概念。同时,操作系统被经过中通信为发出Socket的概念,但这Socket就无是基于网络传输层的商谈了。

那找有该按钮并也底补充加Event Handler的代码如下:

8.1 Unix中的Socket

操作系统被吗时有发生使及Socket这个概念用来拓展过程中通信,它与一般性说之依据TCP/IP的Socket概念十分相似,代表了在操作系统被传输数据的个别正在,只是她不再基于网络协议,而是操作系统本身的文件系统。

 

8.2 网络中之Socket

平凡所说的Socket
API,是凭借操作系统中(也可能不是操作系统)提供的对污染输层(TCP/UDP)抽象的接口。现行的Socket
API大致都是比照了BSD
Socket规范(包括Windows)。这里称规范其实不太规范,规范其实是POSIX,但BSD
Unix中对此Socket的落实叫广为使用,所以成为了实际的正规化。如果您若用HTTP来构建服务,那么即便未待关注Socket,如果您想冲TCP/IP来构建服务,那么Socket可能就是您见面硌到的API。

▲ 在TCP/IP网络中HTTP的位置

起达图备受好看看,HTTP是因传输层的TCP协议的,而Socket
API也是,所以只是从以及说,可以当Socket和HTTP类似(但一个凡是文章的互联网协议,一个凡一直沿用的等同种编程概念),是对于传输层协商的另外一样种植直接运用,因为按照统筹,网络对用户之接口都应有以应用层。

HtmlDocument htmlDoc = webBrowser.Document;
HtmlElement btnElement = htmlDoc.All[“btnClose”];
if (btnElement != null)
{
    btnElement.click += new HtmlElementEventHandler(HtmlBtnClose_Click);
}

8.3 Socket名称的案由

暨博别样Internet上之物一样,Socket这个名号来于红的ARPANET(Advanced
Research Projects
Agency),早期ARPANET中之Socket指的凡一个源要么目的地址——大致就是是今咱们所说的IP地址和端口号。最早的时节一个Socket指的凡一个40各类的数字(RFC33中说明了是所以法,但每当RFC36中连从未明显地游说采取40个数字来标识一个地点),其中前32吧对的地址(socket
number,大致相当给IP),后8号呢发送数据的源(link,大致相当给端口号)。对他们的叫法有成千上万底版,这里列举的连无谨慎。

其中HtmlBtnClose_Click是准下Web按钮时底Event Handler。

8.4 端口号的野史

趁着ARPANET的发展,后来(RFC433,Socket Number List)socket
number被明确地定义也一个40号的数字,其中后8各类为用来制定有特定的行使使用(比如1凡Telnet)。这8各数出很多名字:link、socket
name、AEN(another eight
number,看到是名字我啊是醉了),工程师逗逼起来吧是异常拼的。

新生于Internet的正儿八经制定中,才真正的之所以起了port
number这个词。至于为何端口号是16各类之,我思念可能有少数独由,一凡是对此这之工程师来说,如果每个端口号来标识一个主次,65535只端口号为大都够用了。二可能是为着对旅吧,_!!。

颇粗略吧?那么小小高级一点的——我们还懂一个HTML元素可能产生广大饶有的波,而HtmlElement这个类似就让起极其常用、共通的几个。那么,如何响应其他事件吧?这也充分粗略,只需要调用HtmlElement的AttachEventHandler就可了:

8.5 Socket原本的意思

当头提到的历史被采取及之Socket,包括TCP文档中使用到的Socket,其实指的是网络传输中的一端,是一个虚拟化的定义。

btnElement.AttachEventHandler(“onclick”, new EventHandler(HtmlBtnClose_Click)); 
//这无异句等价于上面的btnElement.click += new HtmlElementEventHandler(HtmlBtnClose_Click); 

9、Socket 与 WebSocket 的关系

刚而达到节所述:Socket 其实并无是一个说道,它工作以 OSI
模型会话层(第5交汇),是为了便利大家一直以还底层协议(一般是TCP或UDP)而存在的一个抽象层。

顶早的均等仿照 Socket API 是Berkeley
sockets,采用
C 语言实现。它是 Socket 的事实标准,POSIX sockets
是因它构建的,多种编程语言都随这套 API,在 JAVA、Python
中还能看就套 API 的阴影。

脚摘录一截再易于了解的文字(来自
http和socket之长连和短连接区别):

Socket是应用层与TCP/IP协议族通信的中级软件抽象层,它是同一组接口。在设计模式中,Socket其实就是一个外衣模式,它将纷繁的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组大概的接口就是全部,让Socket去组织数据,以契合指定的商。

长机 A 的应用程序要能够及主机 B 的应用程序通信,必须经过 Socket
建立连接,而树立 Socket 连接要得底层 TCP/IP 协议来树 TCP
连接。建立 TCP 连接要底层 IP
协议来寻址网络被之主机。我们知晓网络层使用的 IP 协议可以帮我们根据
IP
地址来找到对象主机,但是同宝主机上恐怕运行着多只应用程序,如何才能够及指定的应用程序通信将通过
TCP 或 UPD 的地址为就算是端口号来指定。这样就得经一个 Socket
实例唯一象征一个主机上的一个应用程序的通信链路了。

若 WebSocket
则不同,它是一个完好的应用层协议,包含一仿照标准的
API。

从而,从以上吧,WebSocket 更易用,而 Socket 更灵活。

对此其余事件,把”onclick”换成该事件之名字即可了。例如:

9、最后领取一下 HTML5 与 WebSocket 的涉及

WebSocket
API是HTML5正式的一样片段,
但这并无意味着 WebSocket 一定要就此在 HTML
中,或者只能于依据浏览器的应用程序中以。

实际,许多言语、框架和服务器都提供了 WebSocket 支持,例如:

1)基于 C
的libwebsocket.org;

2)基于 Node.js
的Socket.io;

3)基于 Python
的ws4py;

4)基于 C++
的WebSocket++;

5)Apache 对 WebSocket 的支持:Apache Module
mod_proxy_wstunnel;

6)Nginx 对 WebSockets 的支持:NGINX as a WebSockets
Proxy、NGINX
Announces Support for WebSocket
Protocol、WebSocket
proxying;

7)lighttpd 对 WebSocket
的支持:mod_websocket。

formElement.AttachEventHandler(“onsubmit”, new EventHandler(HtmlForm_Submit)); 

附录:其它Web端即时通讯技术文章

《新手入门贴:史上无与伦比全Web端即时通讯技术原理详解》

《Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE》

《SSE技术详解:一种植新的HTML5服务器推送事件技术》

《Comet技术详解:基于HTTP长连接的Web端实时通信技术》

《新手快速入门:WebSocket简明教程》

《socket.io实现信息推送的一点执行与思路》

《LinkedIn的Web端即时通讯实践:实现单机几十万修长连》

《Web端即时通讯技术之进步及WebSocket、Socket.io的技艺实施》

《Web端即时通讯安全:跨站点WebSocket劫持漏洞详解(含示例代码)》

《开源框架Pomelo实践:搭建Web端高性能分布式IM聊天服务器》

《行使WebSocket和SSE技术实现Web端消息推送》

《详解Web端通信方式的朝三暮四:从Ajax、JSONP 到
SSE、Websocket》

《MobileIMSDK-Web的网络层框架为何采用的是Socket.io而休是Netty?》

>>重多同类文章
……

(本文同步发布给:http://www.52im.net/thread-1273-1-1.html)

**Study Case
2:表单(form)的自行填写跟付
**

设使我们的WebBrowser具有活动填表、甚至电动提交的成效,并无紧。

一经有一个顶简便的登录页面,输入用户名密码,点“登录”按钮即可登录。已解用户称输入框的id(或Name,下同)是username,密码输入框的id是password,“登录”按钮的id是submitbutton,那么我们只有待以webBrowser的DocumentCompleted事件受到使下的代码即可:

HtmlElement btnSubmit = webBrowser.Document.All[“submitbutton”];
HtmlElement tbUserid = webBrowser.Document.All[“username”];
HtmlElement tbPasswd = webBrowser.Document.All[“password”];

if (tbUserid == null || tbPasswd == null || btnSubmit == null)
    return;

tbUserid.SetAttribute(“value”, “smalldust”);
tbPasswd.SetAttribute(“value”, “12345678”);

btnSubmit.InvokeMember(“click”);

这里我们就此SetAttribute来设置文本框的“value”属性,用InvokeMember来调用了按钮的“click”方法。因为不同之Html元素,其兼具的性能和艺术呢不尽相同,所以.Net
2.0资了联合之HtmlElement来概括各种Html元素的以,提供了立即点儿个方法为调用元素特有的功用。关于各种Html元素的属性与法一览,可以查MSDN的DHTML
Reference。

※关于表单的付出,的确还有其它一样种办法就是得form元素而非是button,并据此form元素的submit方法:

HtmlElement formLogin = webBrowser.Document.Forms[“loginForm”]; 
//…… 
formLogin.InvokeMember(“submit”); 

本文之所以没推荐这种办法,是为今天之网页,很多且在submit按钮上补偿加onclick事件,以对交付的情节做尽核心的求证。如果直白下form的submit方法,这些证明代码就得不至实施,有或会见招错误。

Study Case 3:查找并选文本

这次咱们要实现一个同IE一模一样的查找功能,以对Web页面内的文进行搜索。

文件查找要赖TextRange对象的findText方法。但是,.Net里并无这个目标。这是以,.Net
2.0资的HtmlDocument,HtmlWindow,HtmlElement等看似,只不过是针对原本mshtml这个COM组件的不完封装,只提供了mshtml的有些机能。所以广大时分,我们照例要依mshtml来促成我们得之功效。好于这些.Net类都提供了DomDocument这个特性,使得我们很爱把.Net对象转换为COM对象下。下面的代码演示了如何寻找Web页面的文书。
(需要添加mshtml的援,并加上using mshtml;)

 

    public partial class SearchDemo : Form
    {
        // 建立一个追寻用的TextRange(IHTMLTxtRange接口) 
        private IHTMLTxtRange searchRange = null;
        public SearchDemo()
        {
            InitializeComponent();
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            // Document的DomDocument属性,就是拖欠目标中的COM对象。 
            IHTMLDocument2 document = (IHTMLDocument2)webBrowser.Document.DomDocument;
            string keyword = txtKeyword.Text.Trim();
            if (keyword == “”)
                return;

            // IE的检索逻辑就是,如果发选区,就由目前选区开始+1字符处开始查找;没有的言辞就是起页面最初开始查找。 
            // 这个逻辑其实是发生接触未酷适中的,我们这里并非管,和IE一致即可。 
            if (document.selection.type.ToLower() != “none”)
            {
                searchRange = (IHTMLTxtRange)document.selection.createRange();
                searchRange.collapse(true);
                searchRange.moveStart(“character”, 1);
            }
            else
            {
                IHTMLBodyElement body = (IHTMLBodyElement)document.body;
                searchRange = (IHTMLTxtRange)body.createTextRange();
            }

            // 如果找到了,就挑(高亮显示)该重大字;否则弹出信息。 
            if (searchRange.findText(keyword, 1, 0))
            {
                searchRange.select();
            }
            else
            {
                MessageBox.Show(“已找到文档结尾。”);
            }
        }
    } 

至这结束,简单的搜索就干定矣。至于替换功能,看了生一个例子,我深信您便可以触类旁通轻松来定了。

Study Case 4:高亮显示

达到一个事例中我们学会了搜寻文本——究跟到底,对Web页面还是只有读不写。那么,如果说只要拿富有的检索结果高亮显示为?我们迅速会想到将持有匹配的仿颜色、背景改一下虽得了。

先是想到的或许是一直修改HTML文本吧……但是,与SourceCode的高亮显示不同,我们用同时只是需要高亮页面中之公文部分。HTML标签、脚本代码等等是绝对免该去改变的。因此我们不克管方方面面页面的Source
Code读进来然后replace,那样有损坏HTML文件结构的或;我们只能于能分离有文件以及外内容(标签,脚本……)的前提下展开。

具体方法有那么些,下面提供简单只比较简单的章程。

方法一:使用TextRange(IHTMLTxtRange)
发出矣达标一个Case的底子,相信大家这会想到用TextRange。没错,TextRange除了提供找寻方法外,还提供了一个pasteHTML方法,以指定的HTML文本替换当前TextRange中之始末。代码片断如下:

    public partial class HilightDemo : Form
    {
        // 定义高亮显示效果的标签。
        string tagBefore = “<span style=’background-color:yellow;color:black’>”;
        string tagAfter = “</span>”;

        // ……

        private void btnHilight_Click(object sender, EventArgs e)
        {
            HtmlDocument htmlDoc = webBrowser.Document;
            string keyword = txtKeyword.Text.Trim();
            if (keyword == “”)
                return;

            object oTextRange = htmlDoc.Body.InvokeMember(“createTextRange”);

            mshtml.IHTMLTxtRange txtrange = oTextRange as mshtml.IHTMLTxtRange;

            while (txtrange.findText(keyword, 1, 4))
            {
                try
                {
                    txtrange.pasteHTML(tagBefore + keyword + tagAfter);
                }
                catch { }
                txtrange.collapse(false);
            }
        }
    }

※这段代码里得到IHTMLTxtRange的法门与方面的事例稍有些不跟,其实所谓条条大路通罗马,本质是一模一样的。

方法二:使用DOM(文档对象模型) 用HTML文档解析为DOM,然后遍历每个节点,在里头搜关键字连进行相应替换处理即可。

    public partial class HilightDemo : Form
    {
        //……

        private void btnHilight_Click(object sender, EventArgs e)
        {
            HTMLDocument document = (HTMLDocument)webBrowser.Document.DomDocument;
            IHTMLDOMNode bodyNode = (IHTMLDOMNode)webBrowser.Document.Body.DomElement;
            string keyword = txtKeyword.Text.Trim();
            if (keyword == “”)
                return;

            HilightText(document, bodyNode, keyword);
        }

        private void HilightText(HTMLDocument document, IHTMLDOMNode node, string keyword)
        {
            // nodeType = 3:text节点
            if (node.nodeType == 3)
            {
                string nodeText = node.nodeValue.ToString();
                // 如果找到了举足轻重字
                if (nodeText.Contains(keyword))
                {
                    IHTMLDOMNode parentNode = node.parentNode;
                    // 将重要字作为分隔符,将文件分离,并逐项添加到原text节点的父节点
                    string[] result = nodeText.Split(new string[] { keyword }, StringSplitOptions.None);
                    for (int i = 0; i < result.Length – 1; i++)
                    {
                        if (result[i] != “”)
                        {
                            IHTMLDOMNode txtNode = document.createTextNode(result[i]);
                            parentNode.insertBefore(txtNode, node);
                        }
                        IHTMLDOMNode orgNode = document.createTextNode(keyword);
                        IHTMLDOMNode hilightedNode = (IHTMLDOMNode)document.createElement(“SPAN”);
                        IHTMLStyle style = ((IHTMLElement)hilightedNode).style;
                        style.color = “black”;
                        style.backgroundColor = “yellow”;
                        hilightedNode.appendChild(orgNode);

                        parentNode.insertBefore(hilightedNode, node);
                    }
                    if (result[result.Length – 1] != “”)
                    {
                            IHTMLDOMNode postNode = document.createTextNode(result[result.Length – 1]);
                            parentNode.insertBefore(postNode, node);
                    }
                    parentNode.removeChild(node);
                } // End of nodeText.Contains(keyword)
            }
            else
            {
                // 如果不是text节点,则递归搜索其子节点
                IHTMLDOMChildrenCollection childNodes = node.childNodes as IHTMLDOMChildrenCollection;
                foreach (IHTMLDOMNode n in childNodes)
                {
                    HilightText(document, n, keyword);
                }
            }
        }
    }

点的少截代码都是以清晰易掌握而简单得不能够更简单的,有广大地方深无圆满。比如,没考虑到如何从高亮显示状态回升;也没有高低写匹配等等。当然,掌握了规律之后相信这些都非会见太碍事。

即半栽艺术各起利弊:
采取TextRange较轻量迅速,而且产生一个杀手锏,就是可以拿过标签(Tag)的重大字挑出来。例如,有如此一段HTML:

<b>Hel</b>lo World!

事先凭作者出于什么目的让Hel三个字母成为粗体,总之显示在页面及之是同等句子“Hello
World!”。在我们愿意高亮页面被的“Hello”这个重点字时,如果因此DOM分析的语句,会汲取含有“Hel”的<b>节点和文件节点“lo
World!”两独节点,因此无法将那个挑出来。而TextRange则能对识别,将那安为高亮。因此也得说TextRange是就和文书有关,和HTML语法结构无关的靶子。

只是,TextRange也产生夫致命弱点,加亮容易,反向的话语就是格外不便。换句话说,去除高亮显示的时刻不可知重就此TextRange,而急需采取其他方法。

倘DOM方法虽然刚好相反,
由于DOM的树状结构特色,虽然非克(或者深麻烦)跨越Tag搜索关键字,但是去高亮显示并无烦。

Study Case 5:与剧本的互操作

以Case 1当中,我们既见到,Web页面的HTML元素的轩然大波,可以由Windows
Form端来响应,可以在某种程度上作为是Web页面调用WinForm;那么回,WinForm除了可直接访问Web页面的HTML元素之外,能否调用Web页面里之各种Script呢?

首先是调用Web页面的台本中就定义好的函数。假设HTML中若下Javascript:

function DoAdd(a, b) {
    return a + b;
}

这就是说,我们要在WinForm调用她,只待如下代码即可:

object oSum = webBrowser.Document.InvokeScript(“DoAdd”, new object[] { 1, 2 });
int sum = Convert.ToInt32(oSum);

下,如果我们怀念实行同样段Web页面中原本没有底台本,该怎么开吧?这次.Net的接近没有供,看来还要靠COM了。IHTMLWindow2可以以轻易的字符串作为脚本代码来实施。

string scriptline01 = @”function ShowPageInfo() {“;
string scriptline02 = @”     var numLinks = document.links.length; “;
string scriptline03 = @”     var numForms = document.forms.length; “;
string scriptline04 = @”     var numImages = document.images.length; “;
string scriptline05 = @”     var numScripts = document.scripts.length; “;
string scriptline06 = @”     alert(‘网页的统计结果:\r\n链接数:’ + numLinks + “;
string scriptline07 = @”        ‘\r\n表单数:’ + numForms + “;
string scriptline08 = @”        ‘\r\n图像数:’ + numImages + “;
string scriptline09 = @”        ‘\r\n脚本数:’ + numScripts);}”;
string scriptline10 = @”ShowPageInfo();”;

string strScript = scriptline01 + scriptline02 + scriptline03 + scriptline04 + scriptline05 +
                   scriptline06 + scriptline07 + scriptline08 + scriptline09 + scriptline10;

IHTMLWindow2 win = (IHTMLWindow2)webBrowser.Document.Window.DomWindow;
win.execScript(strScript, “Javascript”);

发表评论

电子邮件地址不会被公开。 必填项已用*标注