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连接相关的知识非常多,本书不会进行更多的具体介绍,有兴趣可以进一步阅读相关的专业资料和书籍。