10.4.2 使用Socket进行数据传输
通过Android 4.0提供的P2P支持,设备可以发现同一WiFi网络下的Android设备,并且与之交换连接相关的数据。这其中,最重要的就是获取到目标设备的IP地址等信息,有了IP地址(指的是同一WiFi网络下的内网IP地址),该设备就可以使用传统的设备间数据通信方式,建立Socket连接,与目标设备进行数据交换。
Android提供的Socket支持,是基于标准的java.net包。其基本概念和使用方式,都与传统的Socket连接无异。开发者可以在设备上绑定相应的端口,使用UDP、TCP等传输协议在设备间传输数据。其数据交互方式,可以是阻塞或者是非阻塞的,开发者可以根据具体的业务场景进行选择[1]。
如果,开发者只是需要在设备间点对点地进行数据的传输,可以使用TCP连接,在数据接收方建立Socket服务:
//建立Socket服务,等待连接,接收数据
try{
//建立Socket服务,绑定预设的PORT端口,其IP为当前设备IP
ServerSocket serverSocket=new ServerSocket(PORT);
//等待连接,该方法会阻塞线程
Socket client=serverSocket.accept();
//如果有连接进来,打开输出流,读取数据
InputStream inputStream=client.getInputStream();
ReadMessageFromSocket(inputStream);
…
//如果仅是处理一次P2P请求,完成后直接断开连接
//如果需要处理多个请求,需要循环等待连接进入
serverSocket.close();
}catch(IOException e){
//捕获IOException异常,处理连接中的各种问题
…
}
而数据传输方可以根据预设的服务端口,使用Socket客户端连接需要接收数据的设备,将数据传输过去:
//与Socket服务建立连接,传输数据
Socket socket=new Socket();
try{
//先绑定一个本地端口,传入null,表示端口由系统随机分配
socket.bind(null);
//用发现的设备IP和预设的端口,尝试与服务建立连接
//在SOCKET_TIMEOUT时间内未能建立连接,会超时抛出异常
socket.connect((new InetSocketAddress(ip, port)),SOCKET_TIMEOUT);
//连接成功后,打开输出数据流,写入数据
OutputStream outputStream=socket.getOutputStream();
WriteMessageToSocket(outputStream);
}catch(IOException e){
//捕获IOException异常,处理连接中的各种问题
…
}finally{
//如果仅处理一次P2P请求,传输完成后不再需要与服务进行通信
//直接关闭连接,否则,与服务维持连接不断地数据交换
if(socket.isConnected()){
try{
socket.close();
}catch(IOException e){
//关闭时也可能会抛出异常,需要额外地进行处理
}
}
}
在该模式下,传输和发送都是阻塞式的,需要在独立的线程中进行。比如,可以选择使用android.app.IntentService在拥有独立线程的服务组件中建立Socket服务,在界面组件中使用android.os.AsyncTask建立Socket客户端传输数据。具体的实现方式,可以根据业务场景来进行构建。
[1]Socket连接相关的知识非常多,本书不会进行更多的具体介绍,有兴趣可以进一步阅读相关的专业资料和书籍。