前言
介于自己的网络方面知识烂的一塌糊涂,所以准备写相关网络的文章,但是考虑全部写在一篇太长了,所以分开写,希望大家能仔细看,最好可以指出我的错误,让我也能纠正。
1.讲解相关的整个网络体系结构:
2.讲解相关网络的重要知识点,比如很多人都听过相关网络方面的名词,但是仅限于听过而已,什么tcp ,udp ,socket ,websocket, http ,https ,然后webservice是啥,跟websocket很像,socket和websocket啥关系长的也很像,session,token,cookie又是啥。
Android技能树 — 网络小结(3)之HTTP/HTTPS
Android技能树 — 网络小结(4)之socket/websocket/webservice
相关网络知识点小结- cookie/session/token(待写)
3.相关的第三方框架的源码解析,毕竟现在面试个大点的公司,okhttp和retrofit源码是必问的。
Android技能树 — 网络小结(6)之 OkHttp超超超超超超超详细解析
Android技能树 — 网络小结(7)之 Retrofit源码详细解析
正文
1. Socket
我们在网络体系结构小结中提过,TCP/IP的体系结构图为
在传输层中为TCP和UDP,解决了数据之间的运输,但是我们很少直接去调用TCP和UDP,比如我们现在是要用TCP传输数据,你要写代码去进行TCP的三次握手连接和四次挥手断开等,而且可能还要考虑什么滑动窗口,累积确认、分组缓存、流量控制等?所以我们正需要某个类,这个类帮我们封装好了TCP的连接,传输,断开等一系列相关各类操作,是不是就很方便了。没错,这个类就是Socket。
Socket 即套接字,是应用层 与 TCP/IP 协议族通信的中间软件抽象层,表现为一个封装了 TCP / IP协议族 的编程接口(API)
1.Socket不是一种协议,而是一个编程调用接口(API),属于传输层(主要解决数据如何在网络中传输)
2.即:通过Socket,我们才能在Andorid平台上通过 TCP/IP协议进行开发
3.对用户来说,只需调用Socket去组织数据,以符合指定的协议,即可通信
关于Socket的使用,代码一搜一大把,这里我就快速通过,直接讲一下大致代码流程,我们知道现在是为了把一个信息从一台设备到另外一台设备,在网络体系结构小结中提过IP
是用来确定信息最后到哪个目标设备,所以我们一定要知道IP
,到了目标设备后,目标设备可能开启了很多应用程序(多个进程),这时候怎么知道这个数据包到哪个进程呢,这里也会涉及到端口,我们平常写代码,有时候是不是会说某个端口被占用了。所以我们同时除了ip
还要知道端口
。
所以初步是设备A的ip
,设备A的端口
,设备B的ip
,设备B的端口
,换成我们平常的通俗说法就是客户端ip
,客户端端口
,服务端ip
,服务端端口
,外加上我们的Socket用来操作TCP
,同时也可以操作 UDP
,所以同时还有一个协议
。所以最终涉及到这5个元素,socket 通过这5个元素来确定。
具体的Socket代码就不多说了:
客户端:
public class ClientSocket {
public static void main(String args[]) {
String host = "127.0.0.1";
int port = 8919;
try {
Socket client = new Socket(host, port);
Writer writer = new OutputStreamWriter(client.getOutputStream());
writer.write("Hello From Client");
writer.flush();
writer.close();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
复制代码
服务端:
public class Server {
public static void main(String args[]) {
ServerSocket echoServer = null;
String line;
DataInputStream is;
PrintStream os;
Socket clientSocket = null;
try {
echoServer = new ServerSocket(9999);
}
catch (IOException e) {
System.out.println(e);
}
try {
clientSocket = echoServer.accept();
is = new DataInputStream(clientSocket.getInputStream());
os = new PrintStream(clientSocket.getOutputStream());
// As long as we receive data, echo that data back to the client.
while (true) {
line = is.readLine();
os.println(line);
}
} catch (IOException e) {
System.out.println(e);
}
}
}
复制代码
看了代码,我们发现Socket的一个很大的特点就是服务端和客户端可以相互传数据。
这和我们平时的网络交互差别挺大的,毕竟我们平常访问后台接口,很少说后台突然通过这个接口发个数据给客户端是吧,一般都是客户端主动发送接口请求,然后才能拿到相关数据。
2. WebSocket
我们在上面的Socket的相关介绍可以看到,Socket是在运输层做了一层抽象层,是TCP/UDP 的 api工具类,所以Socket不算是应用层类,而我们在相关网络知识点小结- http/https提过Http/Https是属于应用层的,而我们的WebSocket也是属于应用层的。所以说WebSocket和Http/Https是同一层级的。
而我们也经常看到很多所谓的Http与WebSocket的区别文章等,比如:
而我们在上面介绍Socket的时候提过,Socket可以双向通信,所以WebSocket也是可以双向通信的,而在没有双向通信的时候,用Http来进行双向通信更多的是使用长轮询。
在WebSocket API尚未被众多浏览器实现和发布的时期,开发者在开发需要接收来自服务器的实时通知应用程序时,不得不求助于一些“hacks”来模拟实时连接以实现实时通信,最流行的一种方式是长轮询。长轮询主要是发出一个HTTP请求到服务器,然后保持连接打开以允许服务器在稍后的时间响应(由服务器确定)。为了这个连接有效地工作,许多技术需要被用于确保消息不错过,如需要在服务器端缓存和记录多个的连接信息(每个客户)。虽然长轮询是可以解决这一问题的,但它会耗费更多的资源,如CPU、内存和带宽等,要想很好的解决实时通信问题就需要设计和发布一种新的协议。 WebSocket 是伴随HTML5发布的一种新协议。它实现了浏览器与服务器全双工通信(full-duplex),可以传输基于消息的文本和二进制数据
WebSocket和长轮询之间的带宽消耗差异:
而WebSocket连接的时候,也会用到http,因为在最刚开始发出连接请求的时候,也是要借助于现有的HTTP协议,当连接成功后,其他时候直接基于TCP完成通信。
1.首先,客户端发起http请求,经过3次握手后,建立起TCP连接;http请求里存放WebSocket支持的版本号等信息,如:Upgrade、Connection、WebSocket-Version等;
2.然后,服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据;
3.最后,客户端收到连接成功的消息后,开始借助于TCP传输信道进行全双工通信。
当然如果只是了解大概的WebSocket和Http的区别,可以看这篇:WebSocket的原理,以及和Http的关系,用了通俗易懂的例子说明了,更加好记,但是并没有说明具体的详细内容。
详细的可以看看这篇: 【腾云阁】WebSocket 浅析
那我们既然是安卓开发,那我们怎么样使用WebSocket呢,我想现在很多人都应该网络请求这块使用的是Okhttp吧,虽然我们平时就是用Okhttp做简单的http/https请求,但其实它也是支持WebSocket的,具体大家可以直接搜索相关文章
3. WebService
首先如果有人做过相关的 WebService 的话,就会觉得大体上其实和平常的 http 请求差不多,都是发送一个请求,然后接受相应的返回数据,可能最直观的差别是平常我们用 http 发送请求,接收到请求/响应报文中的请求体都是 JSON,而WebService用的是 XML 的形式。其实的确是这样,因为Webservice就是采用了基于http的soap协议传输数据,所以简单理解为soap=http+xml。因为用了xml之后,更加的通用性,对于跨平台跨应用来说都更好的相互通信解析。
XML+XSD,SOAP和WSDL就是构成WebService平台的三大技术。
我们具体一项项来查看:
3.1 XML+XSD
WebService采用HTTP协议传输数据,采用XML格式封装数据(即XML中说明调用远程服务对象的哪个方法,传递的参数是什么,以及服务对象的 返回结果是什么)。XML是WebService平台中表示数据的格式。除了易于建立和易于分析外,XML主要的优点在于它既是平台无关的,又是厂商无关 的。无关性是比技术优越性更重要的:软件厂商是不会选择一个由竞争对手所发明的技术的。
XSD又是什么呢,因为我们平常写xml格式的内容,可以随便写,只要符合基本的xml格式就行,但实际上这样就没有一套标准的数据类型了。所以XML Schema(XSD)就是专门解决这个问题的一套标准。它定义了一套标准的数据类型,并给出了一种语言来扩展这套数据类型
3.2 SOAP
WebService通过HTTP协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明 HTTP消息的内容格式,这些特定的HTTP消息头和XML内容格式就是SOAP协议。SOAP提供了标准的RPC方法来调用Web Service。
所以 SOAP协议 = HTTP协议 + XML数据格式
3.3 WSDL
使用过WebService应该都知道这个,WebService务器端首先要通过一个WSDL文件来说明有啥服务可以对外调用,服务是什么(服务中有哪些方法,方法接受 的参数是什么,返回值是什么),服务的网络地址用哪个url地址表示,服务通过什么方式来调用。
比如下面这个是国内手机号码归属地查询WEB服务:
而且提供了soap1.1/soap1.2/get/post 四种方式来调用获取:
但是实际上可能没有写的这么详细,就是给我们一个WSDL,里面的内容是这样的:
这里有些人可能不知道怎么来读懂这个文件,其实很简单,我们一步步来看:
我们先找到相应的service:
我们可以看到里面有soap1.1,soap1.2, http-get,http-post四种,我们以soap1.2为例,我们可以看到她后面
binding = "tns:MobileCodeWSSoap12"
,所以我们查找相应的binding的值我们搜索到了
MobileCodeWSSoap12
后发现是:所以我们要继续跟踪下去,这下查找的是
type="tns:MobileCodeWSSoap"
我们搜索关键字:
tns:MobileCodeWSSoap
后发现的是:我们可以看到
<wsdl:operation name="getMobileCodeInfo">
,所以我们知道方法名字叫getMobileCodeInfo
,同时下面有<wsdl:input message="tns:getMobileCodeInfoSoapIn"/> 和 <wsdl:output message="tns:getMobileCodeInfoSoapOut"/>
看字面意思就知道是输入参数和输出参数,然后继续对应关键字getMobileCodeInfoSoapIn
和getMobileCodeInfoSoapOut
搜下搜到的结果为:
,然后继续跟踪
getMobileCodeInfo
和getMobileCodeInfoResponse
。最终看到了具体的输入参数和输出参数。
明显输入参数是
mobileCode和userID
,输出参数是getMobileCodeInfoResult
,而且都是字符串类型。
总体来说就是
<service>
-><binding>
-><type>
-><message>
-><element>
那么另外一个问题来了,我们从哪里得到WSDL呢?
WSDL 文件保存在Web服务器上,通过一个url地址就可以访问到它。客户端要调用一个WebService服务之前,要知道该服务的WSDL文件的地址。比如上面我贴图的WSDL内容就是只要访问:ws.webxml.com.cn/WebServices…就可以了。
WebService服务提供商可以通过两种方式来暴露它的WSDL文件地址:1.注册到UDDI服务器,以便被人查找;2.直接告诉给客户端调用者。
补充1 :可能有些人会说WSDL的内容还是看不懂,可以参考 WSDL 教程 及 WebService中的WSDL详细解析 学习。
补充2 : 刚提到了Soap1.1 和 Soap1.2:
结语:
emmmm…….轻喷即可。有错请留言,我可以进行修改。其中文章配图部分引自下面参考文章。
参考文章:
WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)