各位老铁们好,相信很多人对深入剖析:卓越Android开发者必备的网络知识体系都不是特别的了解,因此呢,今天就来为大家分享下关于深入剖析:卓越Android开发者必备的网络知识体系以及的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!
如果你想了解它们之间的异同(或者更具体地说,如果你想更深入地掌握Android开发中的网络通信技术),你必须熟悉网络的基础知识,基础知识Android网络框架原理等,只有在关键时刻才能找到最适合自己APP的网络通信技术实践。
事实证明,在Android的日常开发和源码阅读中,经常会遇到相关知识。掌握这些基础的网络知识也是Android程序员真正迈向高级所需的基本技术素质之一。
鉴于此,本文将主要介绍计算机网络的一些基础知识,以及Android开发中的一些使用和遇到的问题及解决方案。
本篇主要分为以下几部分:1)计算机网络体系结构;
2)Http相关;
3)tcp相关;
4) 插座。
学习交流:即时通讯开发交流群3:185926912 【推荐】移动IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》(本文同步发表于:http://www.52im.net/thread-1963-1-1.html)
2、关于作者
舒大飞:携程网Android开发工程师,作者博客:https://www.jianshu.com/u/ae379336190b。
注:纳入本文时,对内容进行了更详细的修改,以使其更易于理解。
3、计算机网络体系结构
计算机网络体系结构是常见的计算机网络系统的层次结构。还是有必要澄清这一点,以免混淆Http 和Tcp 这两个根本不在同一层的协议。基于不同的参考模型,例如OSI模型和TCP/IP模型,分层结构有多个不同版本。
下面就以比较经常看到的的5层结构为例:图片(更清晰更完整的图片请参见《计算机网络通讯协议关系图(中文珍藏版)[附件下载]》)
如上图所示,五层架构从上到下,最终可以实现端到端的数据传输和通信。他们各自负责什么?最终如何实现端到端的沟通?
1)应用层:例如,http协议实际上定义了如何打包和解析数据。如果应用层是http协议,则会按照协议规定对数据进行打包,比如按照请求行、请求头、请求体进行打包。将数据打包后将数据传递给传输层。
2)运输层:传输层有TCP和UDP两种协议,分别对应可靠传输和不可靠传输。比如TCP需要提供可靠的传输,那么它内部就必须解决如何建立连接,如何保证传输可靠且不丢失数据。如何调整流量控制和拥塞控制。关于这一层,我们通常会和Socket打交道。 Socket是一组封装好的编程调用接口。通过它,我们可以操作TCP、UDP建立连接等。平时我们使用Socket建立连接时,通常会指定一个端口号,所以这一层指定了相应的端口号来发送数据。
3)网络层:这层IP协议,还有一些路由协议等,所以这一层指定了数据要传输到哪个IP地址。中间涉及到一些最优线路、路由算法等。
4)数据链路层:印象最深刻的就是ARP协议,它负责将IP地址解析成MAC地址,即硬件地址,从而可以找到对应的唯一机器。
5)物理层:该层为底层,提供二进制流传输服务,即数据通过传输介质(有线、无线)的实际传输开始。
因此,通过以上五层,各司其职,物理传输介质——MAC地址——IP地址——端口号——获取数据,根据应用层协议解析数据,最终实现网络通信和数据传输。
接下来我重点讲一下HTTP和TCP相关的事情。关于其他层,毕业这么久,已经忘记很多了。如果想对下面三层有更详细、具体的了解,比如路由算法、ARP寻址、物理层等,还是想再看一下《TCP/IP详解 卷1:协议》~
4、HTTP相关
本节主要讲一些关于Http的基础知识,以及在Android中的一些实际应用以及遇到的问题和解决方案。
限于篇幅原因,本文在一些知识点上只做简要性的概述,如果想要全面深入地掌握HTTP协议,请阅读以下文章:《网络编程懒人入门(七):深入浅出,全面理解HTTP协议》
《从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路》
《脑残式网络编程入门(三):HTTP协议必知必会的一些知识》
4.1 正确理解HTTP的“无连接”“与无状态”
HTTP 是无连接和无状态的。
无连接并不意味着不需要连接。 HTTP协议只是一个应用层协议。最终,连接依赖于TCP协议等传输层提供的服务。
无连接的含义是HTTP约定每个连接只处理一个请求,一个请求完成后连接就会断开。这主要是为了减轻服务器的压力,减少连接对服务器资源的占用。我的理解是建立连接其实是传输层的事情。对于应用层的http来说,它是无连接的,因为上层不知道下层。
无状态意味着每个请求都是独立的,没有能力记住之前的请求事务。所以就有了像cookie这样的东西,用来保存一些状态。
4.2 请求报文与响应报文
这里简单讲一下HTTP请求报文和响应报文格式的基础知识。
请求报文:image响应报文:image关于Get和Post,我们都熟知的关于Get和Post的区别大致有以下几点:1)Get会将url后面的所有请求参数拼接起来,最后显示在地址栏,而Post会将请求参数数据放到请求体中,不会显示在地址栏。出来;
2)传递参数的长度限制。
问题:关于第1)点,在浏览器的地址栏上暴露隐私数据确实不合适,但如果是在app开发中,没有地址栏的概念,这还会成为问题吗?选择post 或get 的限制;
关于第2)点,长度限制应该是浏览器限制,与get本身无关。如果是在App开发中,这一点可以忽略吗?
4.3 HTTP的缓存机制
之所以要介绍下面的Http缓存机制,是因为Okhttp使用Http缓存机制来进行网络请求缓存,而不是像Volley等框架中那样由客户端自己写一套缓存策略。
Http缓存主要利用header中的两个字段来控制:Cache-control和ETag,下面将分别介绍。
1)Cache-control主要包含以及几个字段:private: 只有客户端可以缓存;
public: 客户端和代理服务器都可以缓存;
max-age: 缓存过期时间;
no-cache:需要使用比较缓存来验证缓存数据;
no-store: 所有内存都不会被缓存。
实际上就是在这里面设置了一个缓存策略,由服务端第一次通过header下发给客户端,可以看到:max-age:即缓存过期时间,稍后再请求。如果没有超过缓存过期时间,则可以直接使用缓存;
no-cache:表示需要比较缓存来验证缓存的数据。如果打开该字段,即使max-age缓存没有过期,仍然需要向服务器发起请求,确认资源是否更新,是否需要再次请求。数据,至于如何比较和缓存,就是下面提到的Etag的作用了。如果服务器确认资源没有更新,则返回304并取本地缓存。如果有更新则返回最新的资源;
no-store:如果开启该字段,则不会进行缓存,也不会检索缓存。
2)ETag:即用来进行对比缓存,Etag是服务端资源的一个标识码当客户端发送第一个请求时,服务器会发出当前请求资源的识别码Etag。下次请求时,客户端会通过header 中的If-None-Match 带上这个识别码Etag。在服务器端,服务器将客户端发送的Etag与最新的资源Etag进行比较。如果相同,则说明资源没有更新,返回304。
3)小结:通过Cache-control和Etag的配合实现Http缓存机制。更多关于HTTP缓存的知识,请参考文章《脑残式网络编程入门(三):HTTP协议必知必会的一些知识》的相关章节进行详细阅读。
4.4 HTTP的Cookie
如上所述,HTTP协议是无状态的,cookie用于在本地缓存和记住一些状态。一个cookie一般包含domin(域)、path、Expires(过期时间)等几个属性,服务器可以通过在响应头中设置-cookies将状态写入到客户端的Cookie中。下次客户端发起请求时,可以带上cookie。
Android开发中遇到的问题及解决:说到cookie,一般如果你只是做App开发,不会经常遇到,但是如果涉及到WebView的需求,可能会遇到。
说一下我在项目中遇到的一个关于WebView Cookie的令人担忧的往事:需求是这样的:加载的WebView中的H5页面需要登录,所以登录原生页面后我们需要手动更改。将ticket写入WebView的Cookie中,然后WebView中加载的H5页面取出Cookie中的ticket,并由服务器进行验证。
但遇到一个问题:通过Chrome Inspect调试WebView,手动写入的Cookie确实已经写入了,但是发起请求时却没有带上Cookie,导致请求验证失败。经过排查,发现WebView的属性默认是关闭的。造成的,可以通过设置以下代码来打开:
CookieManager cookieManager=CookieManager.getInstance();
if(Build.VERSION.SDK_INT=Build.VERSION_CODES.LOLLIPOP) {
cookieManager.setAcceptThirdPartyCookies(mWebView, true);
} 别的{
cookieManager.setAcceptCookie(true);
}
4.5 Https
我们都知道Https保证了我们数据传输的安全。 https=Http+Ssl。保证安全的主要原则是使用非对称加密算法。常用的对称加密算法之所以不安全,是因为加密和解密双方使用统一的密钥。只要任何一方泄露了密钥,其他人就可以使用该密钥来解密数据。
非对称加密算法之所以能够实现安全传输的核心本质是,公钥加密的信息只能用私钥解密,而私钥加密的信息也只能用公钥解密。
1)简述非对称加密算法为什么安全:服务器在申请CA机构颁发的证书时,获取该证书的公钥和私钥。私钥只有服务器自己知道,公钥可以告知其他人。例如,可以将公钥传递给客户端,这样客户端使用服务器发送的公钥来加密其传输的数据,服务器使用私钥来解密数据。由于客户端用公钥加密的数据只能用私钥解密,而这个私钥只有服务器拥有,所以数据传输是安全的。
以上只是简单介绍了非对称加密算法如何保证数据安全。其实HTTPS的工作过程远比这复杂(限于篇幅这里就不详细说了,网上有很多相关文章):
一是客户端还需要验证服务器发送过来的CA证书的合法性和有效性,因为CA证书在传输过程中存在被转包的风险,这就涉及到客户端如何验证合法性的问题服务器证书,保证通信双方的身份合法;
二是非对称算法虽然保证了数据安全,但与对称算法相比,其效率相对较差。如何优化实现既保证数据安全又提高效率。
2)客户端如何验证证书的合法性:首先CA证书一般包括以下内容:证书的颁发机构及版本;
证书的使用者;
证书的公钥;
证书有效期;
证书的数字签名哈希值和签名哈希算法(这个数字签名哈希值是用证书的私钥加密的值);
ETC。
客户端验证服务器传递的证书的合法性的方式是:首先使用获得的公钥解密证书中的数字签名哈希值1(因为是用私钥加密的),然后使用签名哈希算法生成一个Hash值2,如果两个值相等,则说明该证书合法,服务器可以信任。
3)Android开发中遇到的问题及解决:顺便说一句,项目开发时使用Android WebView加载公司测试服务器上的网页时,证书过期,导致网页加载失败,出现白屏。
解决办法是在测试环境中暂时忽略SSL错误,这样网页就可以加载了。当然,不要在生产中这样做。一是会存在安全问题,二是Google Play不会通过审核。
最佳办法是重写WebViewClient的onReceivedSslError():@覆盖
publicvoidonReceivedSslError(WebView视图,SslErrorHandler处理程序,SslError错误){
如果(ContextHolder.sDebug){
处理程序.继续();
返回;
}
super.onReceivedSslError(视图,处理程序,错误);
}
最后:有关HTTPS更详细、更全面的知识,请深入阅读《即时通讯安全篇(七):如果这样来理解HTTPS原理,一篇就够了》。
4.6 Http 2.0
Okhttp支持Http 2.0协议的配置和使用。与Http1.x相比,Http2.0有巨大的改进,主要有以下几点。
1)二进制格式:http1.x是文本协议,而http2.0是二进制协议。基本单位是框架。它是一个二进制协议。帧除了数据之外,还包含该帧的标识符:Stream Identifier,用于标识该帧。属于哪一个请求,使得网络传输非常灵活;
2)多路复用:一个很大的进步。原来的http1.
为了解决效率问题,http1.x可能会发起尽可能多的并发请求来加载资源。但浏览器对同一域名下的并发请求有限制,优化方法一般是将请求的资源放到不同的域名中。突破这个限制。
http2.0支持的复用可以很好的解决这个问题。多个请求共享一个TCP 连接。多个请求可以同时在此TCP 连接上并发。一是解决建立多个TCP连接的消耗问题。一还解决了效率问题。
那么一个TCP连接上支持多个请求并发的原理是什么呢?基本原理就是上面的二进制分帧。由于每个帧都有一个标识,因此多个请求的不同帧可以同时且无序地发送出去。服务器会将它们组织成相应的请求。
3)header头部压缩:主要是压缩头部,减少请求大小,减少流量消耗,提高效率。因为之前有一个问题,每个请求都必须带一个header,而这个header 中的数据通常是不变的。
4)支持服务端推送。
更多关于HTTP2的知识,请阅读《从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路》。
5、TCP相关
TCP 面向连接,提供可靠的数据传输。在这一层,我们通常通过Socket Api来操作TCP,建立连接等。
5.1 三次握手建立连接
image 第一次:发送SNY=1表示本次握手是建立连接的请求,然后seq生成客户端的随机数X
第二次:SNY=1,发送ACK=1表示建立连接的回复请求,然后ack=客户端的seq+1(这样客户端可以确认是之前自己想要连接的服务器),然后服务器端也生成一个代表自己的随机数seq=Y并发送给客户端。
第三次:ACK=1。 seq=客户端随机数+1,ack=服务器随机数+1(这样服务器就知道刚才是客户端了)
为什么建立连接需要三次握手?首先很明确的是,两次握手是最基本的。第一次握手时,C端向S端发送连接请求消息。 S端收到后,S端就知道可以成功连接C端了。但是C端此时并不知道S端是否收到消息,所以S端收到消息后必须做出响应。 C端只有得到S端的回复后,才能确定可以连接到S端。这是第二次握手。
只有当C端确定可以连接到S端时,才开始发送数据。所以两次握手绝对是最基本的。
那么为什么需要第三次握手呢?假设如果没有第三次握手,但我们认为两次握手后就建立了连接,会发生什么情况?
第三次握手是为了防止失败的连接请求报文段突然被传送到服务器,从而导致错误。
具体情况就是:C端发送的第一个网络连接请求由于某种原因卡在网络节点,导致延迟。直到连接释放的某个时间点才到达S端。这是一条早已过期的消息。但此时S端仍然认为这是C端连接建立请求的第一次握手,因此S端以第二次握手响应C端。
如果只有两次握手,那么这里就建立了连接,但是此时C端没有任何数据要发送,S端就会傻傻地等待,造成资源的巨大浪费。因此,需要进行第三次握手。只有C方再次响应才能避免这种情况。
要想深刻理解TCP三次握手,请不要错过以下文章:《TCP/IP详解第18章·TCP连接的建立与终止》
《通俗易懂-深入理解TCP协议(上):理论基础》
《理论经典:TCP协议的3次握手与4次挥手过程详解》
《理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程》
《脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手》
5.2 四次挥手断开连接
图片经过上面的连接图的分析,这张图应该不难理解了。
这里主要有一个问题:为什么比建立连接时多了一波?
可以看到,这里服务器的ACK(回复客户端)和FIN(终止)报文不是同时发送的,而是先ACK,再FIN。这也很容易理解。当客户端请求断开连接时,此时服务器可能还有未发送的数据,因此先ACK,然后在FIN之前等待数据发送。这成为四次握手。
以上描述了TCP连接建立和断开的过程。 TCP的主要特点是提供可靠的传输。那么它如何保证数据传输的可靠呢?这就是下面要讨论的滑动窗口协议。
相关知识请深入阅读:《理论经典:TCP协议的3次握手与4次挥手过程详解》
《理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程》
《脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手》
5.3 滑动窗口协议
滑动窗口协议是保证TCP可靠传输的基础,因为只有发送窗口收到确认帧后才会向后移动窗口并继续发送其他帧。
下面举个例子:如果发送窗口为3帧
图像最初在前3 帧[1,2,3] 中发送窗口。前3帧可以发送,但后面的帧暂时无法发送。例如,发送[1]帧后,收到接收方的确认。消息,那么此时发送窗口可以后移1帧,发送窗口达到[2,3,4]。同样,只能发送发送窗口内的帧,以此类推。
接收窗口接收到帧后,将其放入相应的位置,然后移动接收窗口。界面窗口也具有与发送窗口相同的大小。如果接收窗口为5帧,则落在接收窗口之外的帧将被丢弃。
发送窗口和接收窗口大小的不同设定就延伸出了不同的协议:图像停等待协议:每发送一帧,必须等待确认消息才能发送下一帧。缺点是:效率较差。
后向N帧协议:采用累积确认的方式。接收方正确接收到N帧后,向发送窗口发送累积确认消息,以确认N帧已正确接收。如果发送方在指定时间内没有收到确认消息,则认为超时或数据丢失,确认帧之后的所有帧都将被重发。缺点:错误序号之后的PDU已经发送完毕,但仍需要再次发送,比较浪费。
选择重传协议:如果发生错误,则只重传错误涉及的所需PDU,提高传输效率,减少不必要的重传。
到这里还剩下最后一个问题:由于发送窗口和接收窗口之间的发送效率和接收效率不匹配,因此会出现拥塞。为了解决这个问题,TCP有一套流量控制和拥塞控制机制。
5.4 流量控制和拥塞控制
1)流量控制:流量控制是控制通信路径上的流量。发送端通过获取接收端的反馈动态调整发送速率,达到控制流量的效果。目的是保证发送方的发送。速度不超过接收器的接收速度。
2)拥塞控制:拥塞控制控制整个通信子网的流量,是全局控制。
慢启动+拥塞避免
我们先看一张经典图:
图像一开始使用慢启动,即拥塞窗口设置为1,然后拥塞窗口指数增长到慢启动阈值(ssthresh=16),然后切换到拥塞避免,即加性增长。增加到一定程度,导致网络出现拥塞,那么拥塞窗口就会再次减少到1,即重新开始慢启动,新的慢启动阈值调整为12,并且很快。
快速重传+快速恢复
快速重传:我们上面提到的重传机制会等到超时还没有从接收方收到消息才开始重传。快速重传的设计思想是:如果发送方收到来自接收方的三个重复的ACK,则可以确定某个消息段丢失。此时,丢失的报文段可以立即重传,无需等待设定的超时时间才开始重传,提高了重传的效率。
快速恢复:上述拥塞控制会在网络拥塞时将拥塞窗口减小到1,并缓慢重新启动。这样做的一个问题是网络无法快速恢复正常状态。快速恢复就是为了优化这个问题而出现的。如果采用快速恢复,当拥塞发生时,拥塞窗口只会减小到新的慢启动门阈值(即12),而不是减小到1,然后直接开始进入拥塞,避免加性增长。如下图所示:
快速重传和快速恢复是对拥塞控制的进一步改进。
要更深入地理解本小节问题,请详读:《TCP/IP详解第21章·TCP的超时与重传》、《通俗易懂-深入理解TCP协议(下):RTT、滑动窗口、拥塞处理》。
6、有关Socket
Socket是一组操作TCP/UDP的API,例如HttpURLConnection、Okhttp等,涉及比较底层的网络请求。最终当然是通过Socket来发送网络请求,而Volley和Retrofit则是更高层次的封装,最终依赖于HttpURLConnection或者Okhttp来进行最终的连接建立和请求发送。
如果你可以简单地使用Socket,那么你应该能够在每一端创建一个Socket。服务器端调用ServerSocket,然后建立连接。
相关资料,请阅读:《网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接》
《脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?》
7、本文小结
当然,以上内容只是我所了解的并且认为非常重要的计算机网络基础知识。还有很多基础的网络知识需要深入理解和探索。写了很多,也算是对我的网络基础知识的一次整理。可能会有一些缺陷,所以我只是将其作为指导。我也请各位专家给我一些建议。
附录:更多网络基础知识文章
《TCP/IP详解第11章·
UDP:用户数据报协议》 《TCP/IP详解第17章·TCP:传输控制协议》 《TCP/IP详解第18章·TCP连接的建立与终止》 《TCP/IP详解第21章·TCP的超时与重传》 《技术往事:改变世界的TCP/IP协议(珍贵多图、手机慎点)》 《通俗易懂-深入理解TCP协议(上):理论基础》 《通俗易懂-深入理解TCP协议(下):RTT、滑动窗口、拥塞处理》 《理论经典:TCP协议的3次握手与4次挥手过程详解》 《理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程》 《计算机网络通讯协议关系图(中文珍藏版)》 《UDP中一个包的大小最大能多大?》 《P2P技术详解(一):NAT详解——详细原理、P2P简介》 《P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解》 《P2P技术详解(三):P2P技术之STUN、TURN、ICE详解》 《通俗易懂:快速理解P2P技术中的NAT穿透原理》 《高性能网络编程(一):单台服务器并发TCP连接数到底可以有多少》 《高性能网络编程(二):上一个10年,著名的C10K并发连接问题》 《高性能网络编程(三):下一个10年,是时候考虑C10M并发问题了》 《高性能网络编程(四):从C10K到C10M高性能网络应用的理论探索》 《高性能网络编程(五):一文读懂高性能网络编程中的I/O模型》 《高性能网络编程(六):一文读懂高性能网络编程中的线程模型》 《不为人知的网络编程(一):浅析TCP协议中的疑难杂症(上篇)》 《不为人知的网络编程(二):浅析TCP协议中的疑难杂症(下篇)》 《不为人知的网络编程(三):关闭TCP连接时为什么会TIME_WAIT、CLOSE_WAIT》 《不为人知的网络编程(四):深入研究分析TCP的异常关闭》 《不为人知的网络编程(五):UDP的连接性和负载均衡》 《不为人知的网络编程(六):深入地理解UDP协议并用好它》 《不为人知的网络编程(七):如何让不可靠的UDP变的可靠?》 《网络编程懒人入门(一):快速理解网络通信协议(上篇)》 《网络编程懒人入门(二):快速理解网络通信协议(下篇)》 《网络编程懒人入门(三):快速理解TCP协议一篇就够》 《网络编程懒人入门(四):快速理解TCP和UDP的差异》 《网络编程懒人入门(五):快速理解为什么说UDP有时比TCP更有优势》 《网络编程懒人入门(六):史上最通俗的集线器、交换机、路由器功能原理入门》 《网络编程懒人入门(七):深入浅出,全面理解HTTP协议》 《网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接》 《技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解》 《让互联网更快:新一代QUIC协议在腾讯的技术实践分享》 《现代移动端网络短连接的优化手段总结:请求速度、弱网适应、安全保障》 《聊聊iOS中网络编程长连接的那些事》 《移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”》 《移动端IM开发者必读(二):史上最全移动弱网络优化方法总结》 《IPv6技术详解:基本概念、应用现状、技术实践(上篇)》 《IPv6技术详解:基本概念、应用现状、技术实践(下篇)》 《从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路》 《脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手》 《脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?》 《脑残式网络编程入门(三):HTTP协议必知必会的一些知识》 《脑残式网络编程入门(四):快速理解HTTP/2的服务器推送(Server Push)》 《以网游服务端的网络接入层设计为例,理解实时通信的技术挑战》 《迈向高阶:优秀Android程序员必知必会的网络基础》【深入剖析:卓越Android开发者必备的网络知识体系】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
做个优秀的安卓开发,网络基础真是太重要了
有10位网友表示赞同!
想写出更强大的app,网络知识可是关键啊!
有20位网友表示赞同!
最近在学安卓,感觉网络方面还是不太了解,这篇文章正好
有12位网友表示赞同!
学习新的东西永远都不嫌晚,高阶网络基础能让我提升不少
有8位网友表示赞同!
我一直想要深入理解Android程序的网络框架,这篇文章或许能帮我
有8位网友表示赞同!
希望通过阅读本文能够更好地掌握网络基础知识
有11位网友表示赞同!
这个标题很吸引人!感觉很有深度,会去看看的
有14位网友表示赞同!
做开发这么多年还是觉得网络基础很重要,还是要加深印象
有16位网友表示赞同!
网络是安卓程序员必备技能之一,这篇文章我看懂了就能提升我好多
有16位网友表示赞同!
终于找到一篇关于高阶网络基础的文章了!我要好好学习一下
有5位网友表示赞同!
想要成为一个优秀的Android程序员,网络基础不可或缺啊
有5位网友表示赞同!
我觉得这篇文章的标题很有干货,一定会收获很多知识
有18位网友表示赞同!
我已经看了其他几篇关于网络基础的文章,还是感觉这个比别的更有深度
有10位网友表示赞同!
对于想要掌握高阶Android开发技术的人来说,这篇文章非常有参考价值
有18位网友表示赞同!
终于可以解决我在安卓程序开发中遇到的网络问题了!
有18位网友表示赞同!
希望通过阅读这篇文章,能够让我更加了解android的网络体系
有16位网友表示赞同!
我还在学习Android编程,觉得这篇关于网络基础的文章很有用
有8位网友表示赞同!
想要写出高品质的手机应用,网络技术绝对离不开
有6位网友表示赞同!
做安卓程序员的未来还是有很多可能性! 掌握好网络基础才能做得更好
有17位网友表示赞同!