日期: 2021 年 6 月 2 日

浅谈http协议

什么是BS架构
浏览器/服务器模式

优点 分布性强 易维护

什么是协议?
信号的传输总要基于一定的规则,这个规则就是协议

协议很多,http https ws DNS FTP SMTP

什么是http协议
http定义(超文本传输协议)
1
http特点
一定是浏览器主动向服务器发起请求
一次请求都会对应一次响应
服务器响应时间不一定是即时的,但它一定会响应
http状态码
三个数字组成 *个数字是响应的类别,分五种类别

1XX: 我已经收到你的消息了,我正在处理
2XX: 表示我们的请求已经被成功接收,接受
3XX: 重定向
4XX: 客户端错误–请求语法或者请求无法实现
5XX: 服务器端错误

请求方式
GET/POST/PUT/DELETE

区别 (一个数据包还是两个数据包,传参方式不同)

浏览器对地址栏长度的限制
IE浏览器对URL的长度现限制为2048字节。
2.360*速浏览器对URL的长度限制为2118字节。
3.Firefox(Browser)对URL的长度限制为65536字节。
4.Safari(Browser)对URL的长度限制为80000字节。
5.Opera(Browser)对URL的长度限制为190000字节。

http工作原理
首先客户端连接服务器
发送http请求
服务器接收请求并返回http响应
客户端解析HTML内容

B-S想要通信
1.确定基于什么协议(http)
2.表明请求方式(协商数据发送的方式)
3.建立连接(进行三次握手)
4.开始通信
5.断开连接(进行四次挥手)

跨域问题
什么是源?
如果两个页面(接口) 的协议,域名,端口号都相同 我们就认为它们具有相同的 源

什么是同源策略?
同源策略就是浏览器的一个安全限制,它阻止不相同的【域】之间进行数据交互

安全限制具体限制了哪些东西不可以被访问?(非同源限制)
无法读取非同源下的cookie localstorage
无法接触非同源的dom
无法向非同源的地址发送 ajax请求

想要进行数据交互怎么办?
跨【域】

怎么跨域?
1. jsonp方式 (利用js访问不受同源策略限制特性)
2. 跨域资源共享 ( S端 cors )
3. 设置反向代理 ( B端 )
4. …

浅谈HTTP传输(一些基本概念)

1、web传输过程

%title插图%num

客户端发起请求,服务端回应。

2、资源
简单讲能够提供web内容的东西都可以是web资源,比如服务器上某个图片,某些文字,音视频等都可以称作为资源。

3、URI(统一资源标识符)

服务器web资源名被称为URI,给定了 URI,HTTP就可以解析出对象。URI有两种形式,URL和URN。

4、URL(统一资源定位符)
这是*常见的一种形式,它描述了一台特定服务器上某资源的特定位置,明确了如何从一个精确固定的位置获取资源。

大部分URL遵循一种标准格式,这种格式包含三个部分。

*部分位方案。说明了访问资源所使用的协议类型,通常为HTTP协议。

第二部分给出了服务器的因特网地址。

其余部分指定了服务器上某个资源。

5、事务
一个HTTP事务由一条(客户端向服务器端)请求命令和一个(服务器端向客户端)相应结果组成,这种通信是通过名为HTTP报文的格式化数据块进行的。

1) 方法
HTTP支持不同的请求命令,这些命令被称为HTTP方法,这个方法会告诉服务器要执行什么动作

2) 状态码
每条HTTP响应报文返回时都会携带一个状态码,告知客户端请求是否成功,或是是否采取其他操作。
常见的状态码
200  ok  文档正确返回
302  redirect(重定向)到其他地方获取资源
404  not found(未找到)无法找到这个资源

3) 报文
HTTP报文是由一行一行的简单字符串组成,HTTP报文都是纯文本,不是二进制代码,所以人们可以方便的对其进行读写。
HTTP报文包括以下几个部分
起始行:
报文的*行为起始行,在请求报文中永利来说明要做什么,在响应报文中说明出翔了什么状况;文本形式
首部字段:
起始行后面有零个或多个首部字段。每个首部字段都包含一个名字和一个值。两者间用(:)分割。首部以一个空行结束。文本形式
主体:
空行之后就是可选的报文主题了,包括所有类型的数据。请求主体中包括了要发送给Web服务器的数据,响应主体中装载了要返回给客户端的数据。主体中可以是包含任意二进制数据,也可以包含文本。

浅谈HTTP代理存在两种形式

HTTP代理存在两种形式,分别简单介绍如下:

*种是 RFC 7230 – HTTP/1.1: Message Syntax and Routing(即修订后的 RFC 2616,HTTP/1.1 协议的*部分)描述的普通代理。这种代理扮演的是「中间人」角色,对于连接到它的客户端来说,它是服务端;对于要连接的服务端来说,它是客户端。它就负责在两端之间来回传送 HTTP 报文。

第二种是 Tunneling TCP based protocols through Web proxy servers(通过 Web 代理服务器用隧道方式传输基于 TCP 的协议)描述的隧道代理。它通过 HTTP 协议正文部分(Body)完成通讯,以 HTTP 的方式实现任意基于 TCP 的应用层协议代理。这种代理使用 HTTP 的 CONNECT 方法建立连接,但 CONNECT *开始并不是 RFC 2616 – HTTP/1.1 的一部分,直到 2014 年发布的 HTTP/1.1 修订版中,才增加了对 CONNECT 及隧道代理的描述,详见 RFC 7231 – HTTP/1.1: Semantics and Content。实际上这种代理早就被广泛实现。

*种代理

HTTP 客户端向代理发送请求报文,代理服务器需要正确地处理请求和连接(例如正确处理 Connection: keep-alive),同时向服务器发送请求,并将收到的响应转发给客户端。

下面这张图片来自于《HTTP 权威指南》,直观地展示了上述行为:假如我通过代理访问 A 网站,对于 A 来说,它会把代理当做客户端,完全察觉不到真正客户端的存在,这实现了隐藏客户端 IP 的目的。当然代理也可以修改 HTTP 请求头部,通过 X-Forwarded-IP 这样的自定义头部告诉服务端真正的客户端 IP。但服务器无法验证这个自定义头部真的是由代理添加,还是客户端修改了请求头,所以从 HTTP 头部字段获取 IP 时,需要格外小心。

第二种代理

HTTP 客户端通过 CONNECT 方法请求隧道代理创建一条到达任意目的服务器和端口的 TCP 连接,并对客户端和服务器之间的后继数据进行盲转发。
假如我通过代理访问 A 网站,浏览器首先通过 CONNECT 请求,让代理创建一条到 A 网站的 TCP 连接;一旦 TCP 连接建好,代理无脑转发后续流量即可。所以这种代理,理论上适用于任意基于 TCP 的应用层协议,HTTPS 网站使用的 TLS 协议当然也可以。这也是这种代理为什么被称为隧道的原因。对于 HTTPS 来说,客户端透过代理直接跟服务端进行 TLS 握手协商密钥,所以依然是安全的。
*后,HTTP 的认证机制可以跟代理配合使用,使得必须输入正确的用户名和密码才能使用代理。

什么是Web?及web服务器原理

什么是Web?

Web就是一种超文本信息系统,Web的一个主要的概念就是超文本连接,它使得文本不再象一本书一样是固定的线性的。而是可以从一个位置跳到另外的位置。你可以从中获取更多的信息。可以转到别的主题上。想要了解某一个主题的内容只要在这个主题上点一下,就可以跳转到包含这一主题的文档上。正是这种多连接性我们才把它称为Web。
World Wide Web,简称WWW,是英国人TimBerners-Lee 1989年在欧洲共同体的一个大型科研机构任职时发明的。通过WEB,互联网上的资源,可以在一个网页里比较直观的表示出来;而且资源之间,在网页上可以链来链去。在WEB1.0上做出巨大贡献的公司有Netscape,Yahoo和Google。 Netscape研发出*个大规模商用的浏览器,Yahoo的杨致远提出了互联网黄页, 而Google后来居上,推出了大受欢迎的搜索服务。
搜索*大的贡献是,把互联网上海量的信息,用机器初步分了个线索。但是,光知道网页里有哪些关键字,只解决了人浏览网页的需求。所以,Tim-Berners-Lee在提出WWW不久,即开始推崇语义网(Semantic Web)的概念。为什么呢?因为互联网上的内容,机器不能理解。他的理想是,网页制作时和架构数据库时,大家都用一种语义的方式,将网页里的内容表述成机器可以理解的格式。这样,整个互联网就成了一个结构严谨的知识库。从理想的角度,这是很诱人的,因为科学家和机器都喜欢有次序的东西。Berners-Lee关心的是,互联网上数据,及能否被其它的互联网应用所重复引用。举一个例子说明标准数据库的魅力。有个产品叫LiberyLink。装了它后,到Amazon上去浏览时,会自动告诉你某一本书在用户当地的图书馆能否找到,书号是多少等。因为一本书有统一的书号和书名,两个不同的互联网服务(Amazon 和当地图书馆数据库检索)可以公享数据,给用户提供全新服务。
但是,语义网提出之后,曲高和寡,响应的人不多。为什么?因为指望要网页的制作者提供这么多额外的信息去让机器理解一个网页,太难;简直就是人给机器打工。这违反了人们能偷懒就偷懒的本性。看看Google的成功就知道。 Google有个Page Rank技术,将网页之间互相链接的关系,用来做结果排序的一个依据,变相利用了网页制作人的判断力。想一想网页的制作者们,从数量来说,比纯浏览者的数量小得多。但Google就这一个革新,用上了网页的制作者的一部份力量,已将其推上了互联网的顶峰。
所以互联网下一步,是要让所有的人都忙起来,全民织网,然后用软件,机器的力量使这些信息更容易被需要的人找到和浏览。如果说WEB1.0是以数据为核心的网,那我觉得WEB2.0是以人为出发点的互联网。我们看一看*近的一些WEB2.0产品,就可以理解以上观点。
Blog: 用户织网,发表新知识,和其他用户内容链接,进而非常自然的组织这些内容。
RSS: 用户产生内容自动分发,定阅
Podcasting: 个人视频/声频的发布/定阅
SNS: blog+人和人之间的链接
WIKI: 用户共同建设一个大百科全书
从知识生产的角度看,WEB1.0的任务,是将以前没有放在网上的人类知识,通过商业的力量,放到网上去。WEB2.0的任务是,将这些知识,通过每个用户的浏览求知的力量,协作工作,把知识有机的组织起来,在这个过程中继续将知识深化,并产生新的思想火花;
从内容产生者角度看,WEB1.0是商业公司为主体把内容往网上搬,而WEB2.0则是以用户为主,以简便随意方式,通过blog/podcasting 方式把新内容往网上搬;
从交互性看,WEB1.0是网站对用户为主;WEB2.0是以P2P为主。
从技术上看,WEB客户端化,工作效率越来越高。比如像Ajax技术, GoogleMAP/Gmail里面用得出神入化。
我们看到,用户在互联网上的作用越来越大;他们贡献内容,传播内容,而且提供了这些内容之间的链接关系和浏览路径。在SNS里面,内容是以用户为核心来组织的。WEB2.0是以用户为核心的互联网。
那么,这种意义上的WEB2.0,和Tim Berners-Lee的语义网,有什么不同呢?语义网的出发点是数据的规整及可重复被机器调用,提出使用语义化的内容发布工具, 试图从规则和技术标准上使互联网更加有序。 Google等搜索引擎,在没有语义网的情况下,尽可能的给互联网提供了线索。 WEB2.0则是鼓励用户用*方便的办法发布内容(blog/podcasting),但是通过用户自发的(blog)或者系统自动以人为核心(SNS)的互相链接给这些看似凌乱的内容提供索引。因为这些线索是用户自己提供,更加符合用户使用感受。互联网逐渐从以关键字为核心的组织方式和阅读方式,到以互联网用户的个人portal(SNS)为线索,或者以个人的思想脉络(blog/rss)为线索的阅读方式。WEB2.0强调用户之间的协作。WIKI是个典型例子。从这个角度看,互联网是在变得更有序,每个用户都在贡献:要么贡献内容,要么贡献内容的次序.
对下一代互联网的看法,还会有很多的讨论。有一点可以肯定,WEB2.0是以人为核心线索的网。提供更方便用户织网的工具,鼓励提供内容。根据用户在互联网上留下的痕迹,组织浏览的线索,提供相关的服务,给用户创造新的价值,给整个互联网产生新的价值,才是WEB2.0商业之道。

Web的特点:

一、Web是图形化的和易于导航的(navigate)

Web 非常流行的一个很重要的原因就在于它可以在一页上同时显示色彩丰富的图形和文本的性能。在Web之前Internet上的信息只有文本形式。Web可以提供将图形、音频、视频信息集合于一体的特性。同时,Web是非常易于导航的,只需要从一个连接跳到另一个连接,就可以在各页各站点之间进行浏览了。

二、Web与平台无关

无论你的系统平台是什么,你都可以通过Internet访问WWW。浏览WWW对你的系统平台没有什么限制。无论从Windows平台、UNIX平台、Macintosh还是别的什么平台我们都可以访问WWW。对WWW的访问是通过一种叫做浏览器(browser)的软件实现的。如Netscape 的Navigator、NCSA的Mosaic、Microsoft的Explorer等。

三、Web是分布式的

大量的图形、音频和视频信息会占用相当大的磁盘空间,我们甚至无法预知信息的多少。对于Web没有必要把所有信息都放在一起,信息可以放在不同的站点上。只需要在浏览器中指明这个站点就可以了。使在物理上并不一定在一个站点的信息在逻辑上一体化,从用户来看这些信息是一体的。

Web 是动态的

*后,由于各Web站点的信息包含站点本身的信息,信息的提供者可以经常对站上的信息进行更新。如某个协议的发展状况,公司的广告等等。一般各信息站点都尽量保证信息的时间性。所以Web站点上的信息是动态的。经常更新的。这一点是由信息的提供者保证的。

Web动态的特性还表现在Web是交互的。

Web的交互性首先表现在它的超连接上,用户的浏览顺序和所到站点完全由他自己决定。另外通过FORM的形式可以从服务器方获得动态的信息。用户通过填写FORM可以向服务器提交请求,服务器可以根据用户的请求返回相应信息。

Web服务器工作原理:

一个 Web 服务器也被称为 HTTP 服务器,它通过 HTTP 协议与客户端通信。这个客户端通常指的是 Web 浏览器。一个基于 Java 的 Web 服务器用到二个重要的类,java.net.Socket 与 java.net.ServerSocket ,并通过 HTTP 消息通信。因此,本文从讨论 HTTP 与这二个类开始,然后我将解释一个与本文相关的简单的 Web 应用。

The Hypertext Transfer Protocol(HTTP)

HTTP 是一种让 Web 服务器与浏览器(客户端)通过 Internet 发送与接收数据的协议。它是一个请求、响应协议–客户端发出一个请求,服务器响应这个请求。HTTP 运用可靠的 TCP 连接,通常用的 TCP 80 端口。它的*个版本是 HTTP/0.9 ,然后被 HTTP/1.0 取代。当前的版本是 HTTP/1.1 ,由RFC2616(.pdf) 定义。

本节主要对应 HTTP 1.1 ,足够使你充分理解由 Web 服务器程序发出的消息。如果你对更加详细的知识有兴趣,可以参考 RFC2616 。

在 HTTP 中,客户端总是通过建立一个连接与发送一个 HTTP 请求来发起一个事务。服务器不能主动去与客户端联系,也不能给客户端发出一个回叫连接。客户端与服务器端都可以提前中断一个连接。例如,当用一个浏览器下载一个文件时,你可以通过点击“停止”键来中断文件的下载,关闭与服务器的 HTTP 连接。

HTTP 请求

一个 HTTP 请求包含三个部分:

Method-URI-Protocol/Version方法-地址-版本

Request header请求头

Entity body请求实体

下面是一个 HTTP 请求实例:

POST /servlet/default.jsp HTTP/1.1

Accept: text/plain; text/html

Accept-Language: en-gb

Connection: Keep-Alive

Host: localhost

Referer: http://localhost/ch8/SendDetails.htm

User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)

Content-Length: 33

Content-Type: application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

LastName=Franks&FirstName=Michael

The Method-URI-Protocol/Version 在这个请求的*行:

POST /servlet/default.jsp HTTP/1.1

其中 POST 是请求的类型。每个客户端 HTTP 请求可以是 HTTP 规范中指定的许多请求类型中的一种。HTTP 1.1 支持七种类型的请求,它们是 GET,POST,HEAD,OPTIONS,PUT,DELETE,TRACE。其中 GET 与 POST 是 Internet 应用中经常用到的二种请求类型。

URI 完整地指定了 Internet 资源。一个 URI 通常被解析为相对服务器的根目录。这样,它应该总是以一个 ‘/’ 前缀开始。一个 URL 实际上是 URI 的一种类型。

Version 指的是该 HTTP 请求所用到的 HTTP 协议版本。

请求头包含了客户端环境与请求实体的一些有用的信息。例如它包含浏览器设定的语言、实体的长度等等。每条请求头用回车换行符(CRLF)分开。

一个非常重要的空行分开了请求头与实体,它标志着实体内容的开始。一些 Internet 开发书籍认为这个 CRLF 空行是 HTTP 请求的第四个部分。

在上面的 HTTP 请求中,实体只是简单以下的一行:

LastName=Franks&FirstName=Michael

在一个典型的 HTTP 请求中,请求实体内容会长得多。

HTTP 响应

与请求相似,HTTP 响应也由三部分组成:

Protocol-Status code-Description协议状态 描述代码

Response headers响应头

Entity body响应实体

以下是一个 HTTP 响应的实例:

HTTP/1.1 200 OK

Server: Microsoft-IIS/4.0

Date: Mon, 3 Jan 1998 13:13:33 GMT

Content-Type: text/html

Last-Modified: Mon, 11 Jan 1998 13:23:42 GMT

Content-Length: 112

<html>

<head>

<title>HTTP Response Example</title></head><body>

Welcome to Brainy Software

</body>

</html>

响应头的*行类似请求头的*行,告诉你所用的协议是 HTTP 1.1 ,请求成功(200=success),以及没有任何问题。

响应头类似请求头也包含了一些有用的信息。响应的实体响应本身的 HTML 内容。头与实体之间由回车换行的空行(CRLF)分开。

Socket 类

一个 socket 是一个网络连接的端点,它使得一个应用可以从网络读与写。在不同电脑上的二个应用软件能够通过收发字节流而彼此通信。要发一个信息到另一个应用程序,你需要知道它的IP地址,以及它的 socket 端口号。在 Java 中,一个 socket 用 java.net.Socket 来实现。

要创建一个 socket ,你可以用 Socket 类中几个构建方法中的一个。其中一个接受主机名与端口号作为参数:

new Socket(“yahoo.com”, 80);

一旦你成功地创建了一个 Socket 类的实例,你就可以用它去发送与接收字节流了。要发送字节流,你需要呼叫 Socket 类的 getOutputStream 方法来得到一个 java.io.OutputSteam 对象。要发送文本到远程的程序,你通常需要从返回的 OutputStream 创建一个 java.io.PrintWriter 对象。要从连接的另一端接收字节流,你需要呼叫 Socket 类的 getInputStream 方法,它返回一个 java.io.InputStream 对象。

以下代码创建一个可以与本地 HTTP 服务器通信的 socket (127.0.0.1 表示一个本地的主机),发送一个 HTTP 请求,并接收从服务器的响应。它还创建一个 StringBuffer 对象来接受响应,并打印到控制台。

Socket socket= new Socket(“127.0.0.1″, “8080”);

OutputStream os= socket.getOutputStream();

boolean autoflush = true;

PrintWriter out= new PrintWriter( socket.getOutputStream(), autoflush );

BufferedReader in = new BufferedReader(

new InputStreamReader( socket.getInputStream() ));

// send an HTTP request to the web server

out.println(“GET /index.jsp HTTP/1.1”);

out.println(“Host: localhost:8080”);

out.println(“Connection: Close”);

out.println();

// read the response

boolean loop= true;

StringBuffer sb = new StringBuffer(8096);

while (loop) {

if ( in.ready() ) {

int i=0;

while (i!=-1) {

i = in.read();

sb.append((char) i);

}

loop = false;

}

Thread.currentThread().sleep(50);

}

// display the response to the out console

System.out.println(sb.toString());

socket.close();

注意要从 web 服务器得到正确的响应,你必须要发送用 HTTP 协议编译了的 HTTP 请求。如果你看了上面的 HTTP 部分,你应该能够理解上面代码中的 HTTP 请求。

黑客首选–Web 2.0应用程序

日前,全球互联网内容安全领导者趋势科技(东京证交所代号:4704)发布了趋势科技实验室整理分析的“08 年病毒威胁摘要暨-09年病毒趋势预测”。根据这份研究报告指出,2008年亚洲地区的网络罪犯纷纷使用新媒介或针对旧媒介进行改良,用以谋取利益,并且以大规模的网页入侵、AUTORUN 恶意软件、社交诈骗手法与区域性病毒威胁为主要四大类型网络犯罪。进入2009年,值得注意的是:由于Web2.0社交网站的使用率大增,然而网站设计的安全弱点加上Web2.0用户的认知不足,因此,这类网站将成为 Web威胁繁衍的沃土。同时,2009年还需特别留意的还有浏览器与其他Web 应用程序,它们将成为黑客攻击的首要目标!

趋势科技的产品技术顾问徐学龙指出:“2008年,锁定特定用户群与热门网站为目标的病毒攻击手法相当猖獗。在5月份,包括娱乐、政治、购物网、社交网络等各种性质的网站达到病毒入侵的*高峰,全球许多网站被植入了恶意代码,借此感染不知情的网民。该趋势似乎正以令人无法想象的速度持续发展,相当令人忧心。”

 

据趋势科技2008年度数据安全分析报告指出:去年感染比例*高的是以利用USB移动储存装置作为传播媒介的AUTORUN恶意软件,在亚洲区即高达15%的感染比例,而在欧洲、中东及非洲 (EMEA) 地区感染数*高的恶意软件当中也出现其身影,甚至还成功渗透NASA与美国国防部网络。由于企业内部USB移动储存装置不易控管,造成窃取私密数据越来越方便,随之兴起了盗卖个人资料的地下经济。而Web威胁结合USB、Email整合而成的混合式攻击,也使得处理病毒问题日趋复杂,企业MIS人员很难找出造成问题的恶意软件档案,致使企业生产力降低。针对此现象,徐学龙进一步分析:“现今病毒感染途径范围越来越大,光靠单一防护措施已经越来越难以防止,若是没做好环节中的其中一项,将导致企业内部用户感染病毒的频率上升。”

另外报告中提到,在过去一年中黑客擅于利用网民所关心的事件,如四川地震、北京奥运等作为套诱饵制作恶意软件向网民连番攻击,而针对特定地区的独特背景所设计的不同攻击事件也依然层出不穷。举例来说,08年2 月份,中国在线游戏平台联众网站遭恶意软件作者利用安全弱点设下陷阱等待玩家上钩。另外,持续兴风作浪的网络钓鱼诈骗邮件,在08年则锁定Yahoo! Japan拍卖网站用户为攻击目标,使他们面临帐户信息遭窃的风险。

Web 2.0的安全风险及对策

在企业IT世界中,安全风险随处可遇,例如不够强壮的密码,意料之外的电子邮件附件,浏览网页时误点了恶意网址,还有不请自来的流氓软件。诸如防火墙、杀毒软件等安全工具基本可以处理这些安全威胁。不过,随着Web 2.0应用逐渐增多,企业IT部门又迎来了新的安全威胁,传统的安全工具在面对Web 2.0应用时往往显得心有余而力不足,那么企业IT部门应该如何应对Web 2.0应用所带来的安全威胁呢?

Web 2.0应用安全风险加剧

随着互联网和Web 2.0应用的日益普及,无论是个人用户,还是企业用户,都将面临着巨大的安全威胁。

安全公司Sophos曾经表示,每天有15000多个新网页将被感染,90%的Web威胁位于合法的黑客站点上,同时在全部搜索结果中有1%包含被感染的网页。

其中,对于多数IT经理或信息安全管理者来说,社交网站所带来的安全威胁日渐增大。黑客们已经把目光转向了众多知名社交网站。

在过去一年中,著名社交网站Facebook用户已经屡次遭到了多种蠕虫病毒的袭击。恶意分子首先获得某Facebook用户帐户,然后向其好友发送一条消息,告诉他们点击这个链接观看来自谷歌Picasa的相片或者是一段视频。缺乏防范意识的用户点击链接后,会被提示下载一个视频控件,但这实际上是一个传播木马病毒的恶意程序。

去年8月份,Facebook的1800多名用户的信息遭到秘密安装的木马程序窜改。

而微博客Twitter也同样成为网络罪犯散播恶意软件和商业广告讯息的工具。*近Twitter用户就遭遇到了钓鱼攻击,黑客首先用伪冒网站骗取用户的账号和密码,然后向被攻击用户的好友发送销售讯息或利用Twitter特有的缩址服务,欺骗网友进入第三方网站。

除了社交网站之外,其它很多Web 2.0应用同样深受用户喜欢,因为它们非常易用和实用,用户一般主动去安装这些工具,但是同时它们也将其固有的风险引入到了企业此前非常牢固的网络架构之内,让企业数据面临着安全风险。

Web 2.0应用安全防护的难点

对于IT经理来说,防护Web 2.0应用所带来的安全风险是一件非常麻烦的事情,因为这些安全威胁的特点已经与传统的安全威胁有了很大区别。

在过去,可以在网络入口处保护网络终端,但是现在,Web内容逐渐趋于动态化,用户需要持续不断的更新现有内容、共享应用程序,并通过多种渠道进行即时通讯。

很多Web 2.0应用都对算法进行了优化,以确保不被阻挡,另外,这些应用还可以将自己伪装成HTTP、FTP、SMTP和Telnet通信,来绕开防火墙和目前统一威胁管理系统的探测。

另外,企业IT人员无法采取一刀切的形式,禁止员工使用所有Web 2.0应用,这是不现实的。因为这样做只会阻扰员工,切断本应通过这些应用得到的具有潜在价值的商机。

如何应对Web 2.0应用安全风险

企业IT人员需要根据当今世界的Web2.0调整自己的安全策略,为社交网站、博客和所有其他类型的网站创建规则,同时借助于新的安全工具来检测和屏蔽恶意Web 2.0应用。

为了避免Web 2.0应用导致企业数据面临威胁,企业安全人员应对企业内部的核心数据进行分门别类,并通过高质量的加密保证非常有价值的数据不被拦截和非授权用户利用。

另外,加强企业内部员工的安全意识教育,通过不断强化员工的风险意识,实际操作培训等使员工自觉遵守相关的策略,帮助企业避免核心数据从内部泄露。

除了加强安全策略和提高员工安全意识外,市场也在呼唤新的技术来加强对Web 2.0应用的管理和防护。

美国FaceTime Communications公司*近推出了名为ACE的新探测分类技术,“ACE”是应用程序控制引擎(Application Control Engine)的首字母缩写。这种专利安全技术可以扫描网络,识别1400多个Web 2.0应用和5万多个社交网络插件。

扫描网络上的恶意应用程序对IT人士来说或许不是一件新鲜的事情,但是FaceTime的ACE技术关注于扫描Web 2.0应用,这就颇具新意了。

通过FaceTime的ACE,这1400多个Web应用可以被识别,同时更多的社交网络插件也可以被单独认出。不管这些应用使用什么端口、协议或逃避技术,ACE都可以发现并关闭它们。

另外,ACE软件开发工具可以让第三方解决方案提供商进行扩展开发,可以帮助它们的客户管理即时通讯、端对端文件共享、社交网络、Web 2.0、VOIP等方面的应用。

HTTP代理服务器的工作原理

在HTTP通信链上,客户端和目标服务器之间通常存在某些中转代理服务器,它们提供对目标资源的中转访问。一个HTTP请求可能被多个代理服务器转发,后面的服务器称为前面服务器的上游服务器。代理服务器按照其使用方式和作用,分为正向代理服务器、反向代理服务器、透明代理服务器。

正向代理要求客户端自己设置代理服务器的地址。客户的每次请求都将直接发送到该代理服务器,并由代理服务器来请求目标资源。比如处于防火墙内的局域网机器要访问Internet,或者要访问一些被屏蔽掉的国外网站,就需要使用正向代理服务器。

反向代理服务器则被设置在服务器端,因而客户端无须进行任何设置。反向代理服务器来接收Internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从内部服务器上得到的结果返回给客户端。在这种情况下,代理服务器对外就表现为一个真实的服务器。

透明代理只能设置在网关上。用户访问Internet的数据报必然都经过网关,如果在网关上设置代理,则该代理对用户来说显然是透明的。透明代理可以看作正向代理的一种特殊情况。

代理服务器通常还提供缓存目标资源的功能(可选),这样用户下次访问同一资源时速度将很快。

代理服务器工作原理是什么?

网友采纳
一、代理服务器的概念及工作原理
(一)代理服务器的概念
  随着Internet技术的迅速发展,越来越多的计算机连入了Internet。很多公司也将自己公司的局域网接入了Internet。如何快速地访问Internet站点,提高网络的安全性,成为了当今的热门话题。在这种情况下,代理服务器便应运而生了。
  
  1、代理服务器的概念
  
  代理服务器(Proxy Server)是个人网络和Internet服务商之间的中间代理机构,它负责转发合法的网络信息,对转发进行控制和登记。代理服务器作为连接Internet(广域网)与Intranet(局域网)的桥梁,在实际应用中发挥着*其重要的作用,它可用于多个目的,*基本的功能是连接,此外还包括安全性,缓存,内容过滤,访问控制管理等功能。代理服务器,顾名思义就是局域上不能直接上网的机器将上网请求(比如说,浏览某个主页)发给能够直接上网的代理服务器,然后代理服务器代理完成这个上网请求,将它所要浏览的主页调入代理服务器的缓存;然后将这个页面传给请求者。这样局域网上的机器使用起来就像能够直接访问网络一样。并且,代理服务器还可以进行一些网站的过滤和控制的功能,这样就实现了我们控制和节省上网费用。
  
  代理服务器能够让多台没有IP地址的电脑使用其代理功能高速、安全地访问互联网资源。当代理服务器客户端发出一个对外的资源访问请求,该请求先被代理服务器识别并由代理服务器代为向外请求资源。由于一般代理服务器拥有较大的带宽,较高的性能,并且能够智能地缓存已浏览或未浏览的网站内容,因此,在一定情况下,客户端通过代理服务器能更快速地访问网络资源。代理服务器应用的常见例子:拥有上百台电脑的局域网通过一台能够访问外部网络资源的代理服务器而也能访问外部互联网。
2、代理服务器的功能
  (1) 充当局域网与外部网络的连接出口
  充当局域网与外部网络的连接出口,同时将内部网络结构的状态对外屏蔽起来,使外部不能直接访问内部网络。从这一点上说,代理服务器就充当的网关。
  (2)作为防火墙
  代理服务器.可以保护局域网的安全,起防火墙的作用。通过设置防火墙,为公司内部的网络提供安全边界,防止外界的侵入。
  (3)网址过滤和访问权限限制
  代理服务器可以设置IP地址过滤,对外界或内部的Internet地址进行过滤,限制不同用户的访问权限。例如代理服务器可以用来限制封锁IP地址,禁止用户对某些网页进行浏览。
  (4)提高访问速度
  代理服务器将远程服务器提供的数据保存在自己的硬盘上,如果有许多用户同时使用这一个代理服务器,他们对Internet站点所有的访问都会经由这台代理服务器来实现。当有人访问过某一站点后,所访问站点的内容便会被保存在代理服务器的硬盘上,如果下一次有人再要访问这个站点时,这些内容便会直接从代理服务器磁盘中取得,而不必再次连接到远程服务器上去取。因此,它可以节约带宽、提高访问速度。
  
(二)代理服务器的工作原理
  
  代理服务器(Proxy Server)的工作原理是:当客户在浏览器中设置好Proxy Server后,你使用浏览器访问所有WWW站点的请求都不会直接发给目的主机,而是先发给代理服务器,代理服务器接受了客户的请求以后,由代理服务器向目的主机发出请求,并接受目的主机的数据,存于代理服务器的硬盘中,然后再由代理服务器将客户要求的数据发给客户。下面我们来详细说明其工作过程:
  在网络上,当客户端向服务器端请求数据时,服务器端会随即将所需的数据传给客户端。但是这个服务器可能在很远的地方(例如在美国),数据传输需要较长的时间,如果需要同样数据的用户很多,则每次都要重复传送.
1、代理服务器的角色
  代理服务器是为了减少长距离的传送而诞生的。它不仅可以代理客户端向服务器端提出请求,也可以代理服务器传给客户端所需要的数据。
当客户端对服务器端提出请求时,此请求会被送到代理服务器,然后代理服务器会检查本身是否有客户端所需要的数据。如果有,代理服务器便代替服务器将数据传给客户端。而代理服务器一般都是设置距自己传输距离较近的某台代理服务器,所以它传数据给客户端的速度会比从远程服务器传数据要快。
  如果代理服务器没有客户端所请求的数据,它会去服务器获取所需的数据。在代理服务器从服务器端取得数据传给客户端时,自己保存一份,待下次如果有用户提出相同的请求时,便可以将数据直接传过去,而不需要再去服务器端获取了。可见,代理服务器改善网络数据传输阻塞的功能是显而易见的。

解决iOS的cell复用问题

常规配置如下 当超过tableView显示的范围的时候 后面显示的内容将会和前面重复。

// 这样配置的话超过页面显示的内容会重复出现
– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 定义唯一标识
static NSString *CellIdentifier = @”Cell”;
// 通过唯一标识创建cell实例
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// 判断为空进行初始化 –(当拉动页面显示超过主页面内容的时候就会重用之前的cell,而不会再次初始化)
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// 对cell 进行简单地数据配置
cell.textLabel.text = @”text”;
cell.detailTextLabel.text = @”text”;
cell.imageView.image = [UIImage imageNamed:@”4.png”];

return cell;
}
通过以下3方案可以解决

方案一 取消cell的重用机制,通过indexPath来创建cell 将可以解决重复显示问题 不过这样做相对于大数据来说内存就比较吃紧了

// 方案一 通过不让他重用cell 来解决重复显示
– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 定义唯一标识
static NSString *CellIdentifier = @”Cell”;
// 通过indexPath创建cell实例 每一个cell都是单独的
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
// 判断为空进行初始化 –(当拉动页面显示超过主页面内容的时候就会重用之前的cell,而不会再次初始化)
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// 对cell 进行简单地数据配置
cell.textLabel.text = @”text”;
cell.detailTextLabel.text = @”text”;
cell.imageView.image = [UIImage imageNamed:@”4.png”];

return cell;
}
方案二 让每个cell都拥有一个对应的标识 这样做也会让cell无法重用 所以也就不会是重复显示了 显示内容比较多时内存占用也是比较多的和方案一类似

// 方案二 同样通过不让他重用cell 来解决重复显示 不同的是每个cell对应一个标识
– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 定义cell标识 每个cell对应一个自己的标识
NSString *CellIdentifier = [NSString stringWithFormat:@”cell%ld%ld”,indexPath.section,indexPath.row];
// 通过不同标识创建cell实例
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// 判断为空进行初始化 –(当拉动页面显示超过主页面内容的时候就会重用之前的cell,而不会再次初始化)
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// 对cell 进行简单地数据配置
cell.textLabel.text = @”text”;
cell.detailTextLabel.text = @”text”;
cell.imageView.image = [UIImage imageNamed:@”4.png”];

return cell;
}
方案三 只要*后一个显示的cell内容不为空,然后把它的子视图全部删除,等同于把这个cell单独出来了 然后跟新数据就可以解决重复显示

// 方案三 当页面拉动需要显示新数据的时候,把*后一个cell进行删除 就有可以自定义cell 此方案即可避免重复显示,又重用了cell相对内存管理来说是*好的方案 前两者相对比较消耗内存
– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 定义唯一标识
static NSString *CellIdentifier = @”Cell”;
// 通过唯一标识创建cell实例
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// 判断为空进行初始化 –(当拉动页面显示超过主页面内容的时候就会重用之前的cell,而不会再次初始化)
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}else//当页面拉动的时候 当cell存在并且*后一个存在 把它进行删除就出来一个独特的cell我们在进行数据配置即可避免
{
while ([cell.contentView.subviews lastObject] != nil) {
[(UIView *)[cell.contentView.subviews lastObject] removeFromSuperview];
}
}
// 对cell 进行简单地数据配置
cell.textLabel.text = @”text”;
cell.detailTextLabel.text = @”text”;
cell.imageView.image = [UIImage imageNamed:@”4.png”];

return cell;
}

iOS_报错”Collection NSArrayM was mutated while being enumerated”

在通讯录搜索时会不停的遍历数组源,获取匹配的用户信息用于展示,此时出现BUG。

报错:崩溃并报错“Collection <__NSArrayM: 0x166105d0> was mutated while being enumerated”。

原因1:数组遍历时修改了数组。解决方法:定义一个新数组,修改新数组

原因2:不同的线程同时读取和修改了数组。

解决方法:

[userList enumerateObjectsUsingBlock:^(id _Nonnull user, NSUInteger idx, BOOL * stop) {

 

iOS NSAttributedString因cell 复用产生的问题

问题描述:

部分cell中的label需要设置富文本属性,部分不需要。在使用NSAttributedString后,复用的cell同样具有相同效果。

错误使用举例:

cell.lCost.text = “”
cell.lCost.attributedText = nil
if indexPath.row == 10 {
let att = NSAttributedString(string: “\(indexPath.row)”, attributes: [NSAttributedString.Key.foregroundColor:UIColor.red, .underlineStyle:NSUnderlineStyle.single.rawValue])
cell.lCost.attributedText = att
} else {
cell.lCost.text = “\(indexPath.row)”
}
效果:除了row=10的字体颜色是红色外,下滑滚动后部分cell的字体颜色同样是红色。虽然设置了attributedText=nil,但在前面设置了text = “”,使得之前的富文本属性被引用,被保留下来。此现象在iOS10及以前不会存在。

解决方法:删除text = “”

if indexPath.row == 10 {
let att = NSAttributedString(string: “\(indexPath.row)”, attributes: [NSAttributedString.Key.foregroundColor:UIColor.red, .underlineStyle:NSUnderlineStyle.single.rawValue])
cell.lCost.attributedText = att
} else {
cell.lCost.attributedText = NSAttributedString(string: “\(indexPath.row)”)

 

iOS之ReactiveCocoa简介和使用

1.ReactiveCocoa简介

ReactiveCocoa(简称为RAC),是由Github开源的一个应用于iOS和OS开发的新框架,Cocoa是苹果整套框架的简称,因此很多苹果框架喜欢以Cocoa结尾。

2.ReactiveCocoa作用

  • 在我们iOS开发过程中,当某些事件响应的时候,需要处理某些业务逻辑,这些事件都用不同的方式来处理。
  • 比如按钮的点击使用action,ScrollView滚动使用delegate,属性值改变使用KVO等系统提供的方式。
  • 其实这些事件,都可以通过RAC处理
  • ReactiveCocoa为事件提供了很多处理方法,而且利用RAC处理事件很方便,可以把要处理的事情,和监听的事情的代码放在一起,这样非常方便我们管理,就不需要跳到对应的方法里。非常符合我们开发中高聚合,低耦合的思想。

3.编程思想

在开发中我们也不能太依赖于某个框架,否则这个框架不更新了,导致项目后期没办法维护,比如之前Facebook提供的Three20框架,在当时也是神器,但是后来不更新了,也就没什么人用了。因此我感觉学习一个框架,还是有必要了解它的编程思想

编程思想的由来:在开发中我们会遇见各种各样的需求,经常会思考如何快速的完成这些需求,这样就会慢慢形成快速完成这些需求的思想。

先简单介绍下目前咱们已知的编程思想

3.1 面向过程:处理事情以过程为核心,一步一步的实现。

3.2 面向对象:万物皆对象

3.3 链式编程思想:是将多个操作(多行代码)通过点号(.)链接在一起成为一句代码,使代码可读性好。a(1).b(2).c(3)

  • 链式编程特点:方法的返回值是block,block必须有返回值(本身对象),block参数(需要操作的值)
  • 代表:masonry框架。
  • 练习一:模仿masonry,写一个加法计算器,练习链式编程思想。

3.4 响应式编程思想:不需要考虑调用顺序,只需要知道考虑结果,类似于蝴蝶效应,产生一个事件,会影响很多东西,这些事件像流一样的传播出去,然后影响结果,借用面向对象的一句话,万物皆是流。

  • 代表:KVO运用。
  • 练习二:KVO底层实现。

3.5 函数式编程思想:是把操作尽量写成一系列嵌套的函数或者方法调用。

  • 函数式编程本质:就是往方法中传入Block,方法中嵌套Block调用,把代码聚合起来管理
  • 函数式编程特点:每个方法必须有返回值(本身对象),把函数或者Block当做参数,block参数(需要操作的值)block返回值(操作结果)
  • 代表:ReactiveCocoa。
  • 练习三:用函数式编程实现,写一个加法计算器,并且加法计算器自带判断是否等于某个值.

4.ReactiveCocoa编程思想

ReactiveCocoa结合了几种编程风格:

函数式编程(Functional Programming)

响应式编程(Reactive Programming)

所以,你可能听说过ReactiveCocoa被描述为函数响应式编程(FRP)框架。

以后使用RAC解决问题,就不需要考虑调用顺序,直接考虑结果,把每一次操作都写成一系列嵌套的方法中,使代码高聚合,方便管理。

5.如何导入ReactiveCocoa框架

通常都会使用CocoaPods(用于管理第三方框架的插件)帮助我们导入。

PS:CocoaPods教程(http://code4app.com/article/cocoapods-install-usage

练习四:创建一个新的工程,演示下,框架的导入。

注意
* podfile如果只描述pod ‘ReactiveCocoa’, ‘~> 4.0.2-alpha-1’,会导入不成功
这里写图片描述
* 报错信息
这里写图片描述
* 需要在podfile加上use_frameworks,重新pod install 才能导入成功。
这里写图片描述

6.ReactiveCocoa常见类。

学习框架首要之处:个人认为先要搞清楚框架中常用的类,在RAC中*核心的类RACSiganl,搞定这个类就能用ReactiveCocoa开发了。

练习五:介绍常见类

RACSiganl:信号类,一般表示将来有数据传递,只要有数据改变,信号内部接收到数据,就会马上发出数据。

  • 信号类(RACSiganl),只是表示当数据改变时,信号内部会发出数据,它本身不具备发送信号的能力,而是交给内部一个订阅者去发出。
  • 默认一个信号都是冷信号,也就是值改变了,也不会触发,只有订阅了这个信号,这个信号才会变为热信号,值改变了才会触发。
  • 如何订阅信号:调用信号RACSignal的subscribeNext就能订阅。
  • RACSiganl简单使用:
  1. // RACSignal使用步骤:
  2. // 1.创建信号 + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe
  3. // 2.订阅信号,才会激活信号. – (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
  4. // 3.发送信号 – (void)sendNext:(id)value
  5. // RACSignal底层实现:
  6. // 1.创建信号,首先把didSubscribe保存到信号中,还不会触发。
  7. // 2.当信号被订阅,也就是调用signal的subscribeNext:nextBlock
  8. // 2.2 subscribeNext内部会创建订阅者subscriber,并且把nextBlock保存到subscriber中。
  9. // 2.1 subscribeNext内部会调用siganl的didSubscribe
  10. // 3.siganl的didSubscribe中调用[subscriber sendNext:@1];
  11. // 3.1 sendNext底层其实就是执行subscriber的nextBlock
  12. // 1.创建信号
  13. RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  14. // block调用时刻:每当有订阅者订阅信号,就会调用block。
  15. // 2.发送信号
  16. [subscriber sendNext:@1];
  17. // 如果不在发送数据,*好发送信号完成,内部会自动调用[RACDisposable disposable]取消订阅信号。
  18. [subscriber sendCompleted];
  19. return [RACDisposable disposableWithBlock:^{
  20. // block调用时刻:当信号发送完成或者发送错误,就会自动执行这个block,取消订阅信号。
  21. // 执行完Block后,当前信号就不在被订阅了。
  22. NSLog(@“信号被销毁”);
  23. }];
  24. }];
  25. // 3.订阅信号,才会激活信号.
  26. [siganl subscribeNext:^(id x) {
  27. // block调用时刻:每当有信号发出数据,就会调用block.
  28. NSLog(@“接收到数据:%@”,x);
  29. }];
  • RACSubscriber:表示订阅者的意思,用于发送信号,这是一个协议,不是一个类,只要遵守这个协议,并且实现方法才能成为订阅者。通过create创建的信号,都有一个订阅者,帮助他发送数据。

RACDisposable:用于取消订阅或者清理资源,当信号发送完成或者发送错误的时候,就会自动触发它。

  • 使用场景:不想监听某个信号时,可以通过它主动取消订阅信号。

RACSubject:RACSubject:信号提供者,自己可以充当信号,又能发送信号。

  • 使用场景:通常用来代替代理,有了它,就不必要定义代理了。

RACReplaySubject:重复提供信号类,RACSubject的子类。
*  RACReplaySubjectRACSubject区别:
* RACReplaySubject可以先发送信号,在订阅信号,RACSubject就不可以。
*  使用场景一:如果一个信号每被订阅一次,就需要把之前的值重复发送一遍,使用重复提供信号类。
*  使用场景二:可以设置capacity数量来限制缓存的value的数量,即只缓充*新的几个值。

  • RACSubject和RACReplaySubject简单使用:
  1. // RACSubject使用步骤
  2. // 1.创建信号 [RACSubject subject],跟RACSiganl不一样,创建信号时没有block。
  3. // 2.订阅信号 – (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
  4. // 3.发送信号 sendNext:(id)value
  5. // RACSubject:底层实现和RACSignal不一样。
  6. // 1.调用subscribeNext订阅信号,只是把订阅者保存起来,并且订阅者的nextBlock已经赋值了。
  7. // 2.调用sendNext发送信号,遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock。
  8. // 1.创建信号
  9. RACSubject *subject = [RACSubject subject];
  10. // 2.订阅信号
  11. [subject subscribeNext:^(id x) {
  12. // block调用时刻:当信号发出新值,就会调用.
  13. NSLog(@“*个订阅者%@”,x);
  14. }];
  15. [subject subscribeNext:^(id x) {
  16. // block调用时刻:当信号发出新值,就会调用.
  17. NSLog(@“第二个订阅者%@”,x);
  18. }];
  19. // 3.发送信号
  20. [subject sendNext:@“1”];
  21. // RACReplaySubject使用步骤:
  22. // 1.创建信号 [RACSubject subject],跟RACSiganl不一样,创建信号时没有block。
  23. // 2.可以先订阅信号,也可以先发送信号。
  24. // 2.1 订阅信号 – (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
  25. // 2.2 发送信号 sendNext:(id)value
  26. // RACReplaySubject:底层实现和RACSubject不一样。
  27. // 1.调用sendNext发送信号,把值保存起来,然后遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock。
  28. // 2.调用subscribeNext订阅信号,遍历保存的所有值,一个一个调用订阅者的nextBlock
  29. // 如果想当一个信号被订阅,就重复播放之前所有值,需要先发送信号,在订阅信号。
  30. // 也就是先保存值,在订阅值。
  31. // 1.创建信号
  32. RACReplaySubject *replaySubject = [RACReplaySubject subject];
  33. // 2.发送信号
  34. [replaySubject sendNext:@1];
  35. [replaySubject sendNext:@2];
  36. // 3.订阅信号
  37. [replaySubject subscribeNext:^(id x) {
  38. NSLog(@“*个订阅者接收到的数据%@”,x);
  39. }];
  40. // 订阅信号
  41. [replaySubject subscribeNext:^(id x) {
  42. NSLog(@“第二个订阅者接收到的数据%@”,x);
  43. }];
  • RACSubject替换代理
  1. // 需求:
  2. // 1.给当前控制器添加一个按钮,modal到另一个控制器界面
  3. // 2.另一个控制器view中有个按钮,点击按钮,通知当前控制器
  4. 步骤一:在第二个控制器.h,添加一个RACSubject代替代理。
  5. @interface TwoViewController : UIViewController
  6. @property (nonatomic, strong) RACSubject *delegateSignal;
  7. @end
  8. 步骤二:监听第二个控制器按钮点击
  9. @implementation TwoViewController
  10. – (IBAction)notice:(id)sender {
  11. // 通知*个控制器,告诉它,按钮被点了
  12. // 通知代理
  13. // 判断代理信号是否有值
  14. if (self.delegateSignal) {
  15. // 有值,才需要通知
  16. [self.delegateSignal sendNext:nil];
  17. }
  18. }
  19. @end
  20. 步骤三:在*个控制器中,监听跳转按钮,给第二个控制器的代理信号赋值,并且监听.
  21. @implementation OneViewController
  22. – (IBAction)btnClick:(id)sender {
  23. // 创建第二个控制器
  24. TwoViewController *twoVc = [[TwoViewController alloc] init];
  25. // 设置代理信号
  26. twoVc.delegateSignal = [RACSubject subject];
  27. // 订阅代理信号
  28. [twoVc.delegateSignal subscribeNext:^(id x) {
  29. NSLog(@“点击了通知按钮”);
  30. }];
  31. // 跳转到第二个控制器
  32. [self presentViewController:twoVc animated:YES completion:nil];
  33. }
  34. @end

RACTuple:元组类,类似NSArray,用来包装值.

RACSequence:RAC中的集合类,用于代替NSArray,NSDictionary,可以使用它来快速遍历数组和字典。

使用场景:1.字典转模型

RACSequence和RACTuple简单使用

  1. // 1.遍历数组
  2. NSArray *numbers = @[@1,@2,@3,@4];
  3. // 这里其实是三步
  4. // *步: 把数组转换成集合RACSequence numbers.rac_sequence
  5. // 第二步: 把集合RACSequence转换RACSignal信号类,numbers.rac_sequence.signal
  6. // 第三步: 订阅信号,激活信号,会自动把集合中的所有值,遍历出来。
  7. [numbers.rac_sequence.signal subscribeNext:^(id x) {
  8. NSLog(@“%@”,x);
  9. }];
  10. // 2.遍历字典,遍历出来的键值对会包装成RACTuple(元组对象)
  11. NSDictionary *dict = @{@“name”:@“xmg”,@“age”:@18};
  12. [dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
  13. // 解包元组,会把元组的值,按顺序给参数里面的变量赋值
  14. RACTupleUnpack(NSString *key,NSString *value) = x;
  15. // 相当于以下写法
  16. // NSString *key = x[0];
  17. // NSString *value = x[1];
  18. NSLog(@“%@ %@”,key,value);
  19. }];
  20. // 3.字典转模型
  21. // 3.1 OC写法
  22. NSString *filePath = [[NSBundle mainBundle] pathForResource:@“flags.plist” ofType:nil];
  23. NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
  24. NSMutableArray *items = [NSMutableArray array];
  25. for (NSDictionary *dict in dictArr) {
  26. FlagItem *item = [FlagItem flagWithDict:dict];
  27. [items addObject:item];
  28. }
  29. // 3.2 RAC写法
  30. NSString *filePath = [[NSBundle mainBundle] pathForResource:@“flags.plist” ofType:nil];
  31. NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
  32. NSMutableArray *flags = [NSMutableArray array];
  33. _flags = flags;
  34. // rac_sequence注意点:调用subscribeNext,并不会马上执行nextBlock,而是会等一会。
  35. [dictArr.rac_sequence.signal subscribeNext:^(id x) {
  36. // 运用RAC遍历字典,x:字典
  37. FlagItem *item = [FlagItem flagWithDict:x];
  38. [flags addObject:item];
  39. }];
  40. NSLog(@“%@”, NSStringFromCGRect([UIScreen mainScreen].bounds));
  41. // 3.3 RAC高级写法:
  42. NSString *filePath = [[NSBundle mainBundle] pathForResource:@“flags.plist” ofType:nil];
  43. NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
  44. // map:映射的意思,目的:把原始值value映射成一个新值
  45. // array: 把集合转换成数组
  46. // 底层实现:当信号被订阅,会遍历集合中的原始值,映射成新值,并且保存到新的数组里。
  47. NSArray *flags = [[dictArr.rac_sequence map:^id(id value) {
  48. return [FlagItem flagWithDict:value];
  49. }] array];

RACMulticastConnection:用于当一个信号,被多次订阅时,为了保证创建信号时,避免多次调用创建信号中的block,造成副作用,可以使用这个类处理。

使用注意:RACMulticastConnection通过RACSignal的-publish或者-muticast:方法创建.

RACMulticastConnection简单使用:

  1. // RACMulticastConnection使用步骤:
  2. // 1.创建信号 + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe
  3. // 2.创建连接 RACMulticastConnection *connect = [signal publish];
  4. // 3.订阅信号,注意:订阅的不在是之前的信号,而是连接的信号。 [connect.signal subscribeNext:nextBlock]
  5. // 4.连接 [connect connect]
  6. // RACMulticastConnection底层原理:
  7. // 1.创建connect,connect.sourceSignal -> RACSignal(原始信号) connect.signal -> RACSubject
  8. // 2.订阅connect.signal,会调用RACSubject的subscribeNext,创建订阅者,而且把订阅者保存起来,不会执行block。
  9. // 3.[connect connect]内部会订阅RACSignal(原始信号),并且订阅者是RACSubject
  10. // 3.1.订阅原始信号,就会调用原始信号中的didSubscribe
  11. // 3.2 didSubscribe,拿到订阅者调用sendNext,其实是调用RACSubject的sendNext
  12. // 4.RACSubject的sendNext,会遍历RACSubject所有订阅者发送信号。
  13. // 4.1 因为刚刚第二步,都是在订阅RACSubject,因此会拿到第二步所有的订阅者,调用他们的nextBlock
  14. // 需求:假设在一个信号中发送请求,每次订阅一次都会发送请求,这样就会导致多次请求。
  15. // 解决:使用RACMulticastConnection就能解决.
  16. // 1.创建请求信号
  17. RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  18. NSLog(@“发送请求”);
  19. return nil;
  20. }];
  21. // 2.订阅信号
  22. [signal subscribeNext:^(id x) {
  23. NSLog(@“接收数据”);
  24. }];
  25. // 2.订阅信号
  26. [signal subscribeNext:^(id x) {
  27. NSLog(@“接收数据”);
  28. }];
  29. // 3.运行结果,会执行两遍发送请求,也就是每次订阅都会发送一次请求
  30. // RACMulticastConnection:解决重复请求问题
  31. // 1.创建信号
  32. RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  33. NSLog(@“发送请求”);
  34. [subscriber sendNext:@1];
  35. return nil;
  36. }];
  37. // 2.创建连接
  38. RACMulticastConnection *connect = [signal publish];
  39. // 3.订阅信号,
  40. // 注意:订阅信号,也不能激活信号,只是保存订阅者到数组,必须通过连接,当调用连接,就会一次性调用所有订阅者的sendNext:
  41. [connect.signal subscribeNext:^(id x) {
  42. NSLog(@“订阅者一信号”);
  43. }];
  44. [connect.signal subscribeNext:^(id x) {
  45. NSLog(@“订阅者二信号”);
  46. }];
  47. // 4.连接,激活信号
  48. [connect connect];

RACCommand:RAC中用于处理事件的类,可以把事件如何处理,事件中的数据如何传递,包装到这个类中,他可以很方便的监控事件的执行过程。

使用场景:监听按钮点击,网络请求

RACCommand简单使用

  1. // 一、RACCommand使用步骤:
  2. // 1.创建命令 initWithSignalBlock:(RACSignal * (^)(id input))signalBlock
  3. // 2.在signalBlock中,创建RACSignal,并且作为signalBlock的返回值
  4. // 3.执行命令 – (RACSignal *)execute:(id)input
  5. // 二、RACCommand使用注意:
  6. // 1.signalBlock必须要返回一个信号,不能传nil.
  7. // 2.如果不想要传递信号,直接创建空的信号[RACSignal empty];
  8. // 3.RACCommand中信号如果数据传递完,必须调用[subscriber sendCompleted],这时命令才会执行完毕,否则永远处于执行中。
  9. // 三、RACCommand设计思想:内部signalBlock为什么要返回一个信号,这个信号有什么用。
  10. // 1.在RAC开发中,通常会把网络请求封装到RACCommand,直接执行某个RACCommand就能发送请求。
  11. // 2.当RACCommand内部请求到数据的时候,需要把请求的数据传递给外界,这时候就需要通过signalBlock返回的信号传递了。
  12. // 四、如何拿到RACCommand中返回信号发出的数据。
  13. // 1.RACCommand有个执行信号源executionSignals,这个是signal of signals(信号的信号),意思是信号发出的数据是信号,不是普通的类型。
  14. // 2.订阅executionSignals就能拿到RACCommand中返回的信号,然后订阅signalBlock返回的信号,就能获取发出的值。
  15. // 五、监听当前命令是否正在执行executing
  16. // 六、使用场景,监听按钮点击,网络请求
  17. // 1.创建命令
  18. RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  19. NSLog(@“执行命令”);
  20. // 创建空信号,必须返回信号
  21. // return [RACSignal empty];
  22. // 2.创建信号,用来传递数据
  23. return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  24. [subscriber sendNext:@“请求数据”];
  25. // 注意:数据传递完,*好调用sendCompleted,这时命令才执行完毕。
  26. [subscriber sendCompleted];
  27. return nil;
  28. }];
  29. }];
  30. // 强引用命令,不要被销毁,否则接收不到数据
  31. _conmmand = command;
  32. // 3.执行命令
  33. [self.conmmand execute:@1];
  34. // 4.订阅RACCommand中的信号
  35. [command.executionSignals subscribeNext:^(id x) {
  36. [x subscribeNext:^(id x) {
  37. NSLog(@“%@”,x);
  38. }];
  39. }];
  40. // RAC高级用法
  41. // switchToLatest:用于signal of signals,获取signal of signals发出的*新信号,也就是可以直接拿到RACCommand中的信号
  42. [command.executionSignals.switchToLatest subscribeNext:^(id x) {
  43. NSLog(@“%@”,x);
  44. }];
  45. // 5.监听命令是否执行完毕,默认会来一次,可以直接跳过,skip表示跳过*次信号。
  46. [[command.executing skip:1] subscribeNext:^(id x) {
  47. if ([x boolValue] == YES) {
  48. // 正在执行
  49. NSLog(@“正在执行”);
  50. }else{
  51. // 执行完成
  52. NSLog(@“执行完成”);
  53. }
  54. }];

RACScheduler:RAC中的队列,用GCD封装的。

RACUnit :表⽰stream不包含有意义的值,也就是看到这个,可以直接理解为nil.

RACEvent: 把数据包装成信号事件(signal event)。它主要通过RACSignal的-materialize来使用,然并卵。

7.ReactiveCocoa开发中常见用法。

7.1 代替代理:

  • rac_signalForSelector:用于替代代理。

7.2 代替KVO :

  • rac_valuesAndChangesForKeyPath:用于监听某个对象的属性改变。

7.3 监听事件:

  • rac_signalForControlEvents:用于监听某个事件。

7.4 代替通知:

  • rac_addObserverForName:用于监听某个通知。

7.5 监听文本框文字改变:

  • rac_textSignal:只要文本框发出改变就会发出这个信号。

7.6 处理当界面有多次请求时,需要都获取到数据时,才能展示界面

  • rac_liftSelector:withSignalsFromArray:Signals:当传入的Signals(信号数组),每一个signal都至少sendNext过一次,就会去触发*个selector参数的方法。
  • 使用注意:几个信号,参数一的方法就几个参数,每个参数对应信号发出的数据。

7.7 代码演示

  1. // 1.代替代理
  2. // 需求:自定义redView,监听红色view中按钮点击
  3. // 之前都是需要通过代理监听,给红色View添加一个代理属性,点击按钮的时候,通知代理做事情
  4. // rac_signalForSelector:把调用某个对象的方法的信息转换成信号,就要调用这个方法,就会发送信号。
  5. // 这里表示只要redV调用btnClick:,就会发出信号,订阅就好了。
  6. [[redV rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(id x) {
  7. NSLog(@“点击红色按钮”);
  8. }];
  9. // 2.KVO
  10. // 把监听redV的center属性改变转换成信号,只要值改变就会发送信号
  11. // observer:可以传入nil
  12. [[redV rac_valuesAndChangesForKeyPath:@“center” options:NSKeyValueObservingOptionNew observer:nil] subscribeNext:^(id x) {
  13. NSLog(@“%@”,x);
  14. }];
  15. // 3.监听事件
  16. // 把按钮点击事件转换为信号,点击按钮,就会发送信号
  17. [[self.btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
  18. NSLog(@“按钮被点击了”);
  19. }];
  20. // 4.代替通知
  21. // 把监听到的通知转换信号
  22. [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
  23. NSLog(@“键盘弹出”);
  24. }];
  25. // 5.监听文本框的文字改变
  26. [_textField.rac_textSignal subscribeNext:^(id x) {
  27. NSLog(@“文字改变了%@”,x);
  28. }];
  29. // 6.处理多个请求,都返回结果的时候,统一做处理.
  30. RACSignal *request1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  31. // 发送请求1
  32. [subscriber sendNext:@“发送请求1”];
  33. return nil;
  34. }];
  35. RACSignal *request2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  36. // 发送请求2
  37. [subscriber sendNext:@“发送请求2”];
  38. return nil;
  39. }];
  40. // 使用注意:几个信号,参数一的方法就几个参数,每个参数对应信号发出的数据。
  41. [self rac_liftSelector:@selector(updateUIWithR1:r2:) withSignalsFromArray:@[request1,request2]];
  42. }
  43. // 更新UI
  44. – (void)updateUIWithR1:(id)data r2:(id)data1
  45. {
  46. NSLog(@“更新UI%@ %@”,data,data1);
  47. }
  • 8.ReactiveCocoa常见宏。

8.1 RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于给某个对象的某个属性绑定。

基本用法

  1. // 只要文本框文字改变,就会修改label的文字
  2. RAC(self.labelView,text) = _textField.rac_textSignal;

8.2 RACObserve(self, name):监听某个对象的某个属性,返回的是信号。

基本用法

  1. [RACObserve(self.view, center) subscribeNext:^(id x) {
  2. NSLog(@“%@”,x);
  3. }];

8.3  @weakify(Obj)和@strongify(Obj),一般两个都是配套使用,解决循环引用问题.

8.4 RACTuplePack:把数据包装成RACTuple(元组类)

基本用法

  1. // 把参数中的数据包装成元组
  2. RACTuple *tuple = RACTuplePack(@10,@20);

8.5 RACTupleUnpack:把RACTuple(元组类)解包成对应的数据。

基本用法

  1. // 把参数中的数据包装成元组
  2. RACTuple *tuple = RACTuplePack(@”xmg“,@20);
  3. // 解包元组,会把元组的值,按顺序给参数里面的变量赋值
  4. // name = @”xmg” age = @20
  5. RACTupleUnpack(NSString *name,NSNumber *age) = tuple;
友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速