Android网络编程
基于TCP协议的网络通信
TCP/IP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路。一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信了。Java使用Socket对象来代表两端的通信接口,并通过Socket产生IO流来进行网络通信。
TCP协议基础
IP协议是Internet上使用的一个关键协议,全称是Internet Protocol(Internet协议),简称为IP协议。通过使用这个协议,使得Internet成为一个允许连接不同类型的计算机和不同操作系统的网络。
如果要使两台计算机彼此之间进行通信,两台计算机必须使用同一种“语言”,IP协议只保证计算机能发送和接收分组数据。IP协议负责将消息从一个主机传送到另一个主机,消息在传送的过程中被分割成一个个小包。
TCP协议被称为一种端对端协议。它为两台计算机之间的连接起了重要作用:当一台计算机需要与另一台远程计算机连接时,TCP协议会让它们建立一个连接(用于发送和接收数据的虚拟链路)。
TCP协议负责收集信息包,并将其按适当的次序放好传送,在接收端收到后再将其正确地还原。TCP协议保证了数据包在传送中准确无误。
TCP协议使用重发机制:当一个通信实体发送一个消息给另一个通信实体后,需要收到另一个通信实体的确认信息,如果没有收到另一个通信实体的确认信息,则会再次重发刚才发送的消息。
TCP协议的通信示意图如下所示:

虽然IP和TCP两个协议的功能不相同,也可以分开单独使用,但它们是在同一个时期作为一个协议来设计的,并且在功能上是互补的。两者结合,才能保证Internet在复杂的环境下正常运行。凡是要连接到Internet的计算机,都必须同时安装和使用这两个协议,因此统称为TCP/IP协议。
使用ServerSocket创建TCP服务器端
Java中能接收其他通信实体连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状态。ServerSocket包含一个监听来自客户端连接请求的方法。
- Socket accept():如果接收到一个客户端Socket的连接请求,该方法将返回一个与连接客户端Socket对应的Socket;否则该方法将一直处于等待状态,线程也被阻塞。
- ServerSocket(int port):用指定的端口port来创建一个ServerSocket。该端口应该有一个有效的端口整数值0~65535。
- ServerSocket(int port,int backlog):增加一个用来改变连接队列长度的参数backlog。
- ServerSocket(int port,int backlog,InetAddress localAddr):在机器存在多个IP地址的情况下,允许通过localAddr这个参数来指定将ServerSocket绑定到指定的IP地址。
当ServerSocket使用完毕后,应使用ServerSocket的close()方法来关闭该ServerSocket。
使用Socket进行通信
客户端通常可以使用Socket的构造器来连接到指定服务器,Socket通常可以提供如下两种构造器:
- Socket(InetAddress/String remoteAddress,int port):创建连接到指定远程主机、远程端口的Socket,该构造器没有指定本地地址、本地端口,默认使用本机主机的默认IP地址,默认使用系统动态分配的端口。
- Socket(InetAddress/String remoteAddress,int port,InetAddress localAddr,int localPort):创建连接到指定远程主机、远程端口的Socket,并指定本地IP地址和本地端口,适用于本地主机有多个IP地址的情形。
Socket提供了如下两个方法来获取输入流和输出流:
- InputStream getInputStream():返回该Socket对象对应的输入流,让程序通过该输入流从Socket中取出数据。
- OutputStream getOutputStream():返回该Socket对象对应的输出流,让程序通过该输出流向Socket中输出数据。
加入多线程
服务器端应该包含多条线程,每个Socket对应一条线程,该线程负责读取Socket对应输入流的数据,并将读到的数据向每个Socket输出流发送一遍,因此需要在服务器端使用List来保存所有的Socket。
每个客户端应该包含两条线程:一条负责生成主界面,响应用户动作,并将用户输入的数据写入Socket对应的输出流中;另一条负责读取Socket对应输入流中的数据,并负责将这些数据在程序界面上显示出来。
使用URL访问网络资源
URL(Uniform Resource Locator)代表统一资源定位符,它是指向互联网“资源”的指针。资源既可以是简单的文件或目录,也可以是对更复杂的对象的引用,例如对数据库或搜索引擎的查询。通常情况下,URL由协议名、主机、端口和资源组成,满足下面的格式:
**protocol://host:port/resourceName**
URL提供了以下方法来访问该URL对应的资源:
- String getFile():获取此URL的资源名。
- String getHost():获取此URL的主机名。
- String getPath():获取此URL的路径部分。
- int getPort():获取此URL的端口号。
- String getProtocol():获取此URL的协议名称。
- String getQuery():获取此URL的查询字符串部分。
- URLConnection openConnection():返回一个URLConnection对象,它表示到URL所引用的远程对象的连接。
- InputStream openStream():打开与此URL的连接,并返回一个用于读取该URL资源的InputStream。
用URLConnection提交请求
URL的openConnection()方法将返回一个URLConnection对象,这个对象表示应用程序和URL之间的通信连接。程序可以通过URLConnection实例向该URL发送请求,读取URL引用的资源。
通常情况下,创建一个和URL的连接,并发送请求、读取此URL引用的资源需要如下几个步骤:
- 通过调用URL对象的openConnection()方法来创建URLConnection对象。
- 设置URLConnection的参数和普通请求属性。
- 如果只是发送GET方式的请求,那么使用connect方法建立和远程资源之间的实际连接即可;如果需要发送POST方式的请求,则需要获取URLConnection实例对应的输出流来发送请求参数。
- 远程资源变为可用,程序可以访问远程资源的头字段,或通过输入流读取远程资源的数据。
在建立和远程资源的实际连接之前,程序可以通过如下方法来设置请求头字段:
- setAllowUserInteraction:设置该URLConnection的allowUserInteraction请求头字段的值。
- setDoInput:设置该URLConnection的doInput请求头字段的值。
- setDoOutput:设置该URLConnection的doOutput请求头字段的值。
- setIfModidiedSince:设置该URLConnection的ifModifiedSince请求头字段的值。
- setUseCaches:设置URLConnection的useCaches请求头字段的值。
使用如下方法来设置或增加通用的头字段:
- setRequestProperty(String key , String value):设置该URLConnection的key请求头字段的值value。
- addRequestProperty(String key , String value):为该URLConnection的key请求头字段增加value值,该方法并不会覆盖原请求头字段的值,而是将新值追加到原请求头字段中。
程序可以使用以下方法来访问头字段和内容:
- Object getContent():获取该URLConnection的内容。
- String getHeaderField(String name):获取指定响应头字段的值。
- getInputStream():返回该URLConnection对应的输入流,用于获取URLConnection响应的内容。
- getOutputStream():返回该URLConnection对应的输出流,用于向URLConnection发送请求参数。
Java提供了以下方法来访问特定响应头字段的值:
- getContentEncoding():获取content-encoding响应头字段的值。
- getContentLength():获取content-length响应头字段的值。
- getContentType():获取content-type响应头字段的值。
- getDate():获取date响应头字段的值。
- getExpiration():获取expires响应头字段的值。
- getLastModified():获取last-modified响应头字段的值。
使用HTTP访问网络
HttpURLConnection是URLConnection的一个子类,在URLConnection的基础上增加了一些用于操作HTTP资源的便捷方法。
使用HttpURLConnection
它在URLConnection的基础上提供了如下便捷的方法:
- int getResponseCode():获取服务器的响应代码。
- String getResponseMessage():获取服务器的响应消息。
- String getRequestMethod():获取发送请求的方法。
- void setRequestMethod(String method):设置发送请求的方法。
程序可按照如下步骤实现多线程下载:
- 创建URL对象。
- 获取指定URL对象所指向资源的大小,此处用到了HttpURLConnection类。
- 在本地磁盘上创建一个与网络资源相同大小的空文件。
- 计算每条线程应该下载网络资源的哪个部分。
- 依次创建、启动多条线程来下载网络资源的指定部分。
使用Apache HttpClient
使用HttpClient发送请求、接收响应很简单,只要如下几步:
- 创建HttpClient对象。
- 如果需要发送GET请求,则创建HttpGet对象;如果需要发送POST请求,则创建HttpPost对象。
- 如果需要发送请求参数,则可调用HttpGet、HttpPost共同的setParams(HttpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
- 调用HttpClient对象的execute(HttpUriRequest request)方法发送请求,执行该方法返回一个HttpResponse。
- 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
Android 5.0 增强的WebView
WebView组件本身就是一个浏览器实现,Android 5.0增强的WebView基于Chromium M37,直接支持WebRTC、WebAudio和WebGLS。
使用WebView浏览网页
WebView提供了大量方法来执行浏览器操作,如下所示:
- void goBack():后退。
- void goForward():前进。
- void loadUrl(String url):加载指定URL对应的网页。
- boolean zoomIn():放大网页。
- boolean zoomOut():缩小网页。
使用WebView加载HTML代码
WebView提供了下面两个方法:
- loadData(String data , String mimeType , String encoding):该方法可用于加载并显示HTML代码。
- loadDtaWithBaseURL(String baseUrl , String data , String mimeType , ,String encoding , String historyUrl):这个方法是上面方法的增强版,但是它不会产生乱码。参数说明如下:
- data:指定需要加载的HTML代码。
- mimeType:指定HTML代码的MIME类型,对于HTML代码可指定为text/html。
- encoding:指定HTML代码编码所用的字符集。比如指定为CBK。
使用WebView中的JavaScript调用Android方法
为了让WebView中的JavaScript脚本调用Android方法,WebView提供了一个配套的WebSettings工具类,这个工具类提供了大量方法来管理WebView的选项设置,其中它的setJavaScriptEnabled(true)
即可让WebView中的JavaScript脚本来调用Android方法。除此之外,为了把Android对象暴露给WebView中JavaScript代码,WebView提供了addJavascriptInterface(Object object , String name)
方法,该方法负责把object对象暴露成JavaScript中的name对象。
在WebView的JavaScript中调用Android方法只要如下三个步骤:
- 调用WebView关联的WebSettings的setJavaScriptEnabled(true)启用JavaScript调用功能。
- 调用WebView的addJavascriptInterface(Object object , String name)方法将object对象暴露给JavaScript脚本。
- 在JavaScript脚本中通过刚才暴露的name对象调用Android方法。
使用Web Service进行网络编程
Web Service平台概述
Web Service平台主要涉及的技术有SOAP、WSDL、UDDI。
1. SOAP(简单对象访问协议)
SOAP是一种具有扩展性的XML消息协议。SOAP允许一个应用程序向另一个应用程序发送XML消息,SOAP消息是从SOAP发送者传至SOAP接收者的单路消息,任何应用程序均可作为发送者或接收者。
SOAP消息包含如下三种主要元素:
- <Envelope.../>根元素,SOAP消息对应的XML文档以该元素作为根元素。
- 可选的<Header../>元素,包含SOAP消息的头信息。
- 必需的<Body.../>元素,包含所有的调用和响应信息。
2.WSDL(Web Service描述语言)
WSDL使用XML描述Web Service ,包括访问和使用Web Service所必需的信息,定义该Web Service的位置、功能及如何通信等描述信息。
一份WSDL文件清晰地定义了三个方面的内容:
- WHAT部分:用于定义Web Service所提供的操作,也就是Web Service能做些什么。
- HOW部分:用于定义如何访问Web Service,包括数据格式详情和访问Web Service操作的必要协议。
- WHERE部分:用于定义Web Service位于何处。
一份WSDL文档通常可分为两个部分:第一部分定义了服务接口;第二部分定义了服务实现。
3.UDDI(统一描述、发现和整合协议)
UDDI是一套信息注册规范,具有如下特点:
- 基于Web;
- 分布式。
UDDI包括一组允许企业向外注册Web Service,以使其他企业发现访问的实现标准。
使用Android应用调用Web Service
为Android应用增加ksoap2-android支持请按如下步骤:
- 登录http://code.google.com/p/ksoap2-android/站点,该站点有介绍下载ksoap2-android项目的方法。
- 下载项目的jar包。
- 将下载得到的JAR包添加到Android项目的libs目录下,并通过Project面板选中该JAR包后,通过右键菜单的“Add as library”菜单项添加该JAR包。
使用ksoap2-android调用Web Service操作的步骤如下:
- 创建HttpTransportSE对象,该对象用于调用Web Service操作。
- 创建SoapSerializationEnvelope对象。
- 创建SoapObject对象,创建该对象时需要传入所要调用Web Service的命名空间、Web Service方法名。
- 如果有参数需要传给Web Service服务器端,则调用SoapObject对象的addProperty(String name , Object value)方法来设置参数,该方法的name参数指定参数名;value参数指定参数值。
- 调用SoapSerializationEnvelope的setOutputSoapObject()方法,或者直接对bodyOut属性赋值,将创建的SoapObject对象设为SoapSerializationEnvelope的传出SOAP消息体。
- 调用对象的call()方法,并以SoapSerializationEnvelope作为参数调用远程Web Service。
- 调用完成后,访问SoapSerializationEnvelope对象的bodyIn属性,该属性返回一个SoapObject对象,该对象就代表了Web Service的返回消息。解析该SoapObject对象,即可获取调用Web Service的返回值。
好的,到此结束!睡觉咯!

网友评论