网络通信应该包含三部分的内容:发送方、接收方、协议栈。发送方和接收方是参与通信的主体,协议栈是发送方和接收方进行通信的契约。按照服务类型,网络通信可分为面向连接和无连接的方式。面向连接是在通信前建立通信链路,而通信结束后释放该链路。无连接的方式则不需要在通信前建立通信连接,这种方式不保证传输的质量。
Android提供了多种网络通信的方式,如Java中提供的网络编程,在Android中都提供了支持。Android中常用的网络编程方式如下:
- 针对TCP/IP协议的Socket和ServerSocket;
- 针对HTTP协议的网络编程,如HttpURLConnection和HttpClient;
- 直接使用WebKit访问网络。
Socket通信
Socket通信是指双方采用Socket机制交换数据。Socket是比较低层的网络编程方式,其他的高级协议(如HTTP)都是建立在此基础之上的,而且Socket是跨平台的编程方式,可以在异构语言之间进行通信,所以掌握Socket网络编程是掌握其他网络编程方式的基础。
Socket和ServerSocket
Socket通常称为“套接字”,这个套接字用来描述通信链的句柄:IP地址和端口。通过套接字,应用程序之间可以传输信息。常见的网络协议有TCP和UDP两种,TCP协议是可靠的、面向连接的协议,这种方式需要在通信前建立通信双方的连接链路,而通信结束后又释放该链路。而UDP数据报协议是不可靠的、无连接的协议,这种协议不需要在通信前建立通信双方的连接。因而UDP牺牲可靠性来降低传输开销,其传输开销比TCP小。
java.net包中提供了一下两个Socket类。
- java.net.Socket是客户端的Socket对应的类;
- java.net.ServerSocket是服务器端的Socket对应的类,这个类表示一个等待客户端连接的服务器端套接字。
Socket类:
Socket类常用的方法如下表所示
方法 | 功能描述 |
Socket(String host,int port) | Socket提供7个构造函数。该构造函数带两个参数,用于创建一个到主机位host、端口号为port的套接字,并连接到远程主机 |
bind(SocketAdderss localAddr) | 将该Socket同参数localAddr指定的地址和端口绑定 |
InetAddress getInetAddress() | 获取该Socket连接的目标主机的IP地址 |
synchronized int getReceiveBufferSize() | 获取该Socket的接收缓冲区的尺寸 |
synchronized void close() | 关闭Socket |
InputStream getInputStream() | 获取该Socket的输入流,这个输入流用来读取数据 |
boolean isConnected() | 判断该Socket是否连接 |
boolean isOutputShutdown() | 判断该Socket的输出管道是否关闭 |
boolean isInputShutdown() | 判断该Socket的输入管道是否关闭 |
SocketAddress getLocalSocketAddress() | 获取此Socket的本地地址和端口 |
int getPort() | 获取端口号 |
一般情况下,Socket的工作步骤如下:
- 根据指定地址和端口号创建一个Socket对象
- 调用getInputStream()方法或getOutputStream()方法打开连接到Socket的输入/出流。
- 客户端与服务器根据一定的协议交互,知道关闭连接。
- 关闭客户端的Socket。
下面代码是一个Socket客户端
1 public class TCPClient{
2 public static void main(String args[]){
3 try{
4 //创建一个Socket对象,指定服务器端的IP地址和端口号
5 Socket socket=new Socket("192.168.1.88",4700);
6 //使用InputStream读取硬盘上的文件
7 InputStream inputStream=new FileInputStream("f://file/words.txt");
8 //从Socket当中得到OutputStream
9 OutputStream outputStream=socket.getOutputStream();
10 byte buffer[]=new byte[4*1024];
11 int temp=0;
12 //将InputStream当中的数据取出,并写入到OutputStream当中
13 while((temp=inputStream.read(buffer))!=-1){
14 outputStream.write(buffer,0,temp);
15 }
16 outputStream.flush();
17 }catch(Exception e){
18 e.printStackTrace();
19 }
20 }
21 }
22 /* UDP客户端
23 * public class UDPClient{
24 public static void main(String args[]){
25 try{
26 //首先创建一个DatagramSocket对象
27 DatagramSocket socket=new DatagramSocket(4567);
28 //创建一个InetAddress
29 InetAddress serverAddress=InetAddress.getByName("192.168.1.88");
30 String str="hello";
31 byte data[]=str.getBytes();
32 //创建一个DatagramPacket对象,并指定要将这个数据包发送到网络当中的哪个地址以及端口号
33 DatagramPacket packet=new DatagramPacket(data,data.length,serverAddress,4567);
34 //调用socket对象的send方法,发送数据
35 socket.send(packet);
36 }catch(Exception e){
37 e.printStackTrace();
38 }
39 }
40 }
ServerSocket类:
ServerSocket用于监听在特定端口的TCP连接、当客户端的Socket试图与服务器指定端口建立连接时,服务器被激活,判定客户程序的连接,一旦客户端与服务器建立了连接,则两者之间就可以相互传送数据、ServerSocket常用的方法如下表
方法 | 功能描述 |
ServerSocket(int Port) | ServerSocket构造函数 |
Socket accept() | 等待客户端的连接,当客户端请求连接时,返回一个Socket |
void close() | 关闭服务器Socket |
SocketAddress getLocalSocketAddress() | 获取此Socket的本地地址和端口 |
int getLocalPort() | 获取端口号 |
InetAddress getInetAddress() | 获取该Socket的IP地址 |
boolean isClosed() | 判断连接是否关闭 |
void setSo Timeout(int timeout) | 设置accept的超时时间 |
一般情况下,ServerSocket的工作步骤如下:
- 根据指定端口创建一个新的ServerSocket对象
- 调用ServerSocket的accept()方法,在指定的端口监听到来的连接。accept()一直处于阻塞状态,直到有客户端试图建立连接。这时accept()方法返回连接客户端与服务器的Socket对象。
- 调用getInputStream()方法或getOutputStream()方法建立与客户端交互的输入/输出流。
- 服务器与客户端根据一定的协议交互,直到关闭连接。
- 关闭服务器端的Socket。
- 回到第2步,继续监听下一次的连接。
下面代码片段是一个服务器端ServerSocket的线程。
1 new Thread()
2 {
3 public void run(){
4 //声明一个ServerSocket对象
5 ServerSocket serverSocket=null;
6 try{
7 //创建一个ServerSocket对象在端口4700监听客户请求
8 serverSocket=new ServerSocket(4700);
9 //调用ServerSocket的accept()方法,接收客户端所发来的请求
10 Socket socket=serverSocket.accept();
11 //从Socket当中得到InputStream对象
12 InputStream inputStream=socket.getInputStream();
13 byte[] buffer[]=new byte[1024*4];
14 int temp=0;
15 //从InputStream当中读取客户端所发送的数据
16 while((temp=inputStream.read(buffer))!=-1){
17 System.out.println(new String(buffer,0,temp));
18 }
19 }catch(IOException e){
20 e.printStackTrace();
21 }
22 finally{
23 try{
24 serverSocket.close();
25 }catch(IOException e){
26 e.printStackTrace();
27 }
28 }
29 }
30 }
31 /*使用UDP协议的服务端
32 *public void run(){
33 try{
34 //创建一个DatagramSocket对象,并指定监听的端口号
35 DatagramSocket socket=new DatagramSocket(4567);
36 byte data[]=new byte[1024];
37 //创建一个空的DatagramPacket对象
38 DatagramSocket packet=new DatagramPacket(data,data.length);
39 //使用receive方法接收客户端所发送的数据
40 socket.receive(packet);
41 String result=new String(packet.getData(),packet.getOffset(),packet.getLength());
42 System.out.println(result);
43 }catch(Exception e){
44 e.printStackTrace();
45 }
46 }
47 }
48 }*/
Android网络通讯简介,码迷,mamicode.com