android socket网络通信
2016-11-29 17:16
627 查看
本文为本人由网上搜集的一些资料的修改整合。
Socket通常称为“套接字”,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。Socket字面上的中文意思为“插座”。一台服务器可能会提供很多服务,每种服务对应一个Socket(也可以这么说,每个Socket就是一个插座,客户若是需要哪种服务,就将插头插到相应的插座上面),而客户的“插头”也是一个Socket。Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。Socket把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。Socket用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过套接字向网络发出请求或者应答网络请求。
应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
总之一句话,socket是对TCP/IP协议的封装。
Socket的基本操作包括:
连接远程机器
发送数据
接收数据
关闭连接
绑定端口
监听到达数据
在绑定的端口上接受来自远程机器的连接
服务器要和客户端通信,两者都要实例化一个Socket。服务器和客户端的Socket是不一样的,客户端可以实现连接远程机器、发送数据、接收数据、关闭连接等,服务器还需要实现绑定端口,监听到达的数据,接受来自远程机器的连接。Android在包java.net里面提供了两个类:ServerSocket和Socket,前者用于实例化服务器的Socket,后者用于实例化客户端的Socket。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成客户端到服务器所需的会话。
接下来分析一些重要的Socket编程接口。首先是如何构造一个Socket,常用的构造客户端Socket的方法有以下几种:
Socket():创建一个新的未连接的Socket。
Socket(Proxy proxy):使用指定的代理类型创建一个新的未连接的Socket。
Socket(String dstName,int dstPort):使用指定的目标服务器的IP地址和目标服务器的端口号,创建一个新的Socket。
Socket(String dstName,int dstPort,InetAddress localAddress,int localPort):使用指定的目标主机、目标端口、本地地址和本地端口,创建一个新的Socket。
Socket(InetAddress dstAddress,int dstPort):使用指定的本地地址和本地端口,创建一个新的Socket。
Socket(InetAddress dstAddress,int dstPort,InetAddress localAddress,int localPort):使用指定的目标主机、目标端口、本地地址和本地端口,创建一个新的Socket。
其中,proxy为代理服务器地址,dstAddress为目标服务器IP地址,dstPort为目标服务器的端口号(因为服务器的每种服务都会绑定在一个端口上面),dstName为目标服务器的主机名。Socket构造函数代码举例如下所示:
注意 0~1023端口为系统保留,用户设定的端口号应该大于1023。
方 法 原 型 功 能 描 述
Public InputStream getInputStream() 读出该Socket中的数据
public OutputStream getOutputStream() 向该Socket中写入数据
public synchronized void close() 关闭该Socket
上面是构造Socket客户端的几种常用的方法,构造服务器端的ServerSocket的方法有以下几种。
ServerSocket():构造一个新的未绑定的ServerSocket。
ServerSocket(int port):构造一个新的ServerSocket实例并绑定到指定端口。如果port参数为0,端口将由操作系统自动分配,此时进入队列的数目将被设置为50。
ServerSocket(int port,int backlog):构造一个新的ServerSocket实例并绑定到指定端口,并且指定进入队列的数目。如果port参数为0,端口将由操作系统自动分配。
ServerSocket(int port,int backlog,InetAddress localAddress):构造一个新的ServerSocket实例并绑定到指定端口和指定的地址。如果localAddress参数为null,则可以使用任意地址,如果port参数为0,端口将由操作系统自动分配。
下面举例说明ServerSocket的构建方法,代码如下所示:
构造完ServerSocket之后,需要调用ServerSocket.accept()方法来等待客户端的请求(因为Socket都是绑定在端口上面的,所以知道是哪个客户端请求的)。accept()方法就会返回请求这个服务的客户端的Socket实例,然后通过返回的这个Socket实例的方法,操作传输过来的信息。当Socket对象操作完毕之后,使用close()方法将其关闭。
方 法 原 型 功 能 描 述
public Socket accept () 等待Socket请求,直到连接被打开,该方法返回一个刚刚打开的连接Socket对象
public void close() 关闭该服务器Socket
Socket一般有两种类型:TCP套接字和UDP套接字。
TCP和UDP在传输过程中的具体实现方法不同。两者都接收传输协议数据包并将其内容向前传送到应用层。TCP把消息分解成数据包(数据报,datagrams)并在接收端以正确的顺序把它们重新装配起来,TCP还处理对遗失数据包的重传请求,位于上层的应用层要处理的事情就少多了。UDP不提供装配和重传请求这些功能,它只是向前传送信息包。位于上层的应用层必须确保消息是完整的,并且是以正确的顺序装配的。
接下来我们分别详细讨论使用TCP和UDP通信的一些细节。
使用TCP通信
TCP建立连接之后,通信双方都同时可以进行数据的传输;在保证可靠性上,采用超时重传和捎带确认机制;在流量控制上,采用滑动窗口协议,协议中规定,对于窗口内未经确认的分组需要重传;在拥塞控制上,采用慢启动算法。
TCP服务器端工作的主要步骤如下。
步骤1 调用ServerSocket(int port)创建一个ServerSocket,并绑定到指定端口上。
步骤2 调用accept(),监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字(socket实例)。
步骤3 调用Socket类的getOutputStream()和getInputStream()获取输出和输入流,开始网络数据的发送和接收。
步骤4 关闭通信套接字。
示例代码如下所示:
步骤1 调用Socket()创建一个流套接字,并连接到服务器端。
步骤2 调用Socket类的getOutputStream()和getInputStream()方法获取输出和输入流,开始网络数据的发送和接收。
步骤3 关闭通信套接字。
编写TCP客户端代码如下所示:
在Android配置文件中需要添加下面的权限:
<uses-permission android:name="android.permission.INTERNET"/>
使用UDP通信
UDP有不提供数据报分组、组装和不能对数据包排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用,包括网络视频会议系统在内的众多的客户端/服务器模式的网络应用都需要使用UDP协议。UDP协议的主要作用是将网络数据流量压缩成数据报的形式。一个典型的数据报就是一个二进制数据的传输单位。UDP传输原理示意图如图2-6所示。
UDP服务器端工作的主要步骤如下。
步骤1 调用DatagramSocket(int port)创建一个数据报套接字,并绑定到指定端口上。
步骤2 调用DatagramPacket(byte[]buf,int length),建立一个字节数组以接收UDP包。
步骤3 调用DatagramSocket类的receive(),接受UDP包。
步骤4 关闭数据报套接字。
示例代码如下所示:
步骤1 调用DatagramSocket()创建一个数据包套接字。
步骤2 调用DatagramPacket(byte[]buf,int offset,int length,InetAddress address,int port),建立要发送的UDP包。
步骤3 调用DatagramSocket类的send()发送UDP包。
步骤4 关闭数据报套接字。
示例代码如下所示:
参考文章:http://book.2cto.com/201308/30046.html
http://www.jb51.net/article/53196.htm
Socket通常称为“套接字”,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。Socket字面上的中文意思为“插座”。一台服务器可能会提供很多服务,每种服务对应一个Socket(也可以这么说,每个Socket就是一个插座,客户若是需要哪种服务,就将插头插到相应的插座上面),而客户的“插头”也是一个Socket。Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。Socket把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。Socket用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过套接字向网络发出请求或者应答网络请求。
应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
总之一句话,socket是对TCP/IP协议的封装。
Socket的基本操作包括:
连接远程机器
发送数据
接收数据
关闭连接
绑定端口
监听到达数据
在绑定的端口上接受来自远程机器的连接
服务器要和客户端通信,两者都要实例化一个Socket。服务器和客户端的Socket是不一样的,客户端可以实现连接远程机器、发送数据、接收数据、关闭连接等,服务器还需要实现绑定端口,监听到达的数据,接受来自远程机器的连接。Android在包java.net里面提供了两个类:ServerSocket和Socket,前者用于实例化服务器的Socket,后者用于实例化客户端的Socket。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成客户端到服务器所需的会话。
接下来分析一些重要的Socket编程接口。首先是如何构造一个Socket,常用的构造客户端Socket的方法有以下几种:
Socket():创建一个新的未连接的Socket。
Socket(Proxy proxy):使用指定的代理类型创建一个新的未连接的Socket。
Socket(String dstName,int dstPort):使用指定的目标服务器的IP地址和目标服务器的端口号,创建一个新的Socket。
Socket(String dstName,int dstPort,InetAddress localAddress,int localPort):使用指定的目标主机、目标端口、本地地址和本地端口,创建一个新的Socket。
Socket(InetAddress dstAddress,int dstPort):使用指定的本地地址和本地端口,创建一个新的Socket。
Socket(InetAddress dstAddress,int dstPort,InetAddress localAddress,int localPort):使用指定的目标主机、目标端口、本地地址和本地端口,创建一个新的Socket。
其中,proxy为代理服务器地址,dstAddress为目标服务器IP地址,dstPort为目标服务器的端口号(因为服务器的每种服务都会绑定在一个端口上面),dstName为目标服务器的主机名。Socket构造函数代码举例如下所示:
Socket client=new Socket("192.168.1.23", 2012); // 第一个参数是目标服务器的IP地址,2012是目标服务器的端口号 Socket sock = new Socket(new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("test.domain.org", 2130))); // 实例化一个Proxy,以该Proxy为参数,创建一个新的Socket
注意 0~1023端口为系统保留,用户设定的端口号应该大于1023。
方 法 原 型 功 能 描 述
Public InputStream getInputStream() 读出该Socket中的数据
public OutputStream getOutputStream() 向该Socket中写入数据
public synchronized void close() 关闭该Socket
上面是构造Socket客户端的几种常用的方法,构造服务器端的ServerSocket的方法有以下几种。
ServerSocket():构造一个新的未绑定的ServerSocket。
ServerSocket(int port):构造一个新的ServerSocket实例并绑定到指定端口。如果port参数为0,端口将由操作系统自动分配,此时进入队列的数目将被设置为50。
ServerSocket(int port,int backlog):构造一个新的ServerSocket实例并绑定到指定端口,并且指定进入队列的数目。如果port参数为0,端口将由操作系统自动分配。
ServerSocket(int port,int backlog,InetAddress localAddress):构造一个新的ServerSocket实例并绑定到指定端口和指定的地址。如果localAddress参数为null,则可以使用任意地址,如果port参数为0,端口将由操作系统自动分配。
下面举例说明ServerSocket的构建方法,代码如下所示:
ServerSocket socketserver=new ServerSocket(2012); // 2012表示服务器要监听的端口号
构造完ServerSocket之后,需要调用ServerSocket.accept()方法来等待客户端的请求(因为Socket都是绑定在端口上面的,所以知道是哪个客户端请求的)。accept()方法就会返回请求这个服务的客户端的Socket实例,然后通过返回的这个Socket实例的方法,操作传输过来的信息。当Socket对象操作完毕之后,使用close()方法将其关闭。
方 法 原 型 功 能 描 述
public Socket accept () 等待Socket请求,直到连接被打开,该方法返回一个刚刚打开的连接Socket对象
public void close() 关闭该服务器Socket
Socket一般有两种类型:TCP套接字和UDP套接字。
TCP和UDP在传输过程中的具体实现方法不同。两者都接收传输协议数据包并将其内容向前传送到应用层。TCP把消息分解成数据包(数据报,datagrams)并在接收端以正确的顺序把它们重新装配起来,TCP还处理对遗失数据包的重传请求,位于上层的应用层要处理的事情就少多了。UDP不提供装配和重传请求这些功能,它只是向前传送信息包。位于上层的应用层必须确保消息是完整的,并且是以正确的顺序装配的。
接下来我们分别详细讨论使用TCP和UDP通信的一些细节。
使用TCP通信
TCP建立连接之后,通信双方都同时可以进行数据的传输;在保证可靠性上,采用超时重传和捎带确认机制;在流量控制上,采用滑动窗口协议,协议中规定,对于窗口内未经确认的分组需要重传;在拥塞控制上,采用慢启动算法。
TCP服务器端工作的主要步骤如下。
步骤1 调用ServerSocket(int port)创建一个ServerSocket,并绑定到指定端口上。
步骤2 调用accept(),监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字(socket实例)。
步骤3 调用Socket类的getOutputStream()和getInputStream()获取输出和输入流,开始网络数据的发送和接收。
步骤4 关闭通信套接字。
示例代码如下所示:
ServerSocket serverSocket = null;//创建一个ServerSocket对象 try { // TCP_SERVER_PORT为指定的绑定端口,为int类型 serverSocket = new ServerSocket(TCP_SERVER_PORT); // 监听连接请求 Socket socket = serverSocket.accept(); // 放到读Buffer中 BufferedReader in = new BufferedReader(new // 获取输入流 InputStreamReader(socket.getInputStream())); // 放到写Buffer中 BufferedWriter out = new BufferedWriter(new // 获取输出流 OutputStreamWriter(socket.getOutputStream())); // 读取接收信息,转换为字符串 String incomingMsg = in.readLine() + System.getProperty("line.separator"); // 生成发送字符串 String outgoingMsg = "goodbye from port " + TCP_SERVER_PORT + System.getProperty("line.separator"); // 将发送字符串写入上面定义的BufferedWriter中 out.write(outgoingMsg); // 刷新,发送 out.flush(); // 关闭 socket.close(); } catch (InterruptedIOException e) { // 超时错误 e.printStackTrace(); // IO异常 } catch (IOException e) { // 打印错误 e.printStackTrace(); } finally { // 判定是否初始化ServerSocket对象,如果初始化则关闭serverSocket if (serverSocket != null) { try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } }TCP客户端工作的主要步骤如下。
步骤1 调用Socket()创建一个流套接字,并连接到服务器端。
步骤2 调用Socket类的getOutputStream()和getInputStream()方法获取输出和输入流,开始网络数据的发送和接收。
步骤3 关闭通信套接字。
编写TCP客户端代码如下所示:
try { // 初始化Socket,TCP_SERVER_PORT为指定的端口,int类型 Socket socket = new Socket("localhost", TCP_SERVER_PORT); // 获取输入流 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 生成输出流 BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); // 生成输出内容 String outMsg = "TCP connecting to " + TCP_SERVER_PORT + System.getProperty("line.separator"); // 写入 out.write(outMsg); // 刷新,发送 out.flush(); // 获取输入流 String inMsg = in.readLine() + System.getProperty("line.separator"); Log.i("TcpClient", "received: " + inMsg); // 关闭连接 socket.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }注意 无论是客户端还是服务器端,都要添加UnknownHostException(处理网络异常)和IOException(处理I/O异常)异常处理。
在Android配置文件中需要添加下面的权限:
<uses-permission android:name="android.permission.INTERNET"/>
使用UDP通信
UDP有不提供数据报分组、组装和不能对数据包排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用,包括网络视频会议系统在内的众多的客户端/服务器模式的网络应用都需要使用UDP协议。UDP协议的主要作用是将网络数据流量压缩成数据报的形式。一个典型的数据报就是一个二进制数据的传输单位。UDP传输原理示意图如图2-6所示。
UDP服务器端工作的主要步骤如下。
步骤1 调用DatagramSocket(int port)创建一个数据报套接字,并绑定到指定端口上。
步骤2 调用DatagramPacket(byte[]buf,int length),建立一个字节数组以接收UDP包。
步骤3 调用DatagramSocket类的receive(),接受UDP包。
步骤4 关闭数据报套接字。
示例代码如下所示:
byte[] lMsg = new byte[MAX_UDP_DATAGRAM_LEN];//接收的字节大小,客户端发送的数据不能超过MAX_UDP_DATAGRAM_LEN // 实例化一个DatagramPacket类 DatagramPacket dp = new DatagramPacket(lMsg, lMsg.length); // 新建一个DatagramSocket类 DatagramSocket ds = null; try { // UDP服务器监听的端口 ds = new DatagramSocket(UDP_SERVER_PORT); // 准备接收数据 ds.receive(dp); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 如果ds对象不为空,则关闭ds对象 if (ds != null) { ds.close(); } }UDP客户端工作的主要步骤如下。
步骤1 调用DatagramSocket()创建一个数据包套接字。
步骤2 调用DatagramPacket(byte[]buf,int offset,int length,InetAddress address,int port),建立要发送的UDP包。
步骤3 调用DatagramSocket类的send()发送UDP包。
步骤4 关闭数据报套接字。
示例代码如下所示:
// 定义需要发送的信息 String udpMsg = "hello world from UDP client " + UDP_SERVER_PORT; // 新建一个DatagramSocket对象 DatagramSocket ds = null; try { // 初始化DatagramSocket对象 ds = new DatagramSocket(); // 初始化InetAddress对象 InetAddress serverAddr = InetAddress.getByName("127.0.0.1"); DatagramPacket dp; // 初始化DatagramPacket对象 dp = new DatagramPacket(udpMsg.getBytes(), udpMsg.length(), serverAddr, UDP_SERVER_PORT); // 发送 ds.send(dp); } // 异常处理 // Socket连接异常 catch (SocketException e) { e.printStackTrace(); // 不能连接到主机 }catch (UnknownHostException e) { e.printStackTrace(); // 数据流异常 } catch (IOException e) { e.printStackTrace(); // 其他异常 } catch (Exception e) { e.printStackTrace(); } finally { // 如果DatagramSocket已经实例化,则需要将其关闭 if (ds != null) { ds.close(); } }
参考文章:http://book.2cto.com/201308/30046.html
http://www.jb51.net/article/53196.htm
相关文章推荐
- Android网络编程之Socket通信
- Android网络编程实践之旅(二):基于Socket的网络通信
- Android网络编程实践之旅(二):基于Socket的网络通信
- Android网络开发之Socket通信
- Android简单的socket网络通信例子--群聊
- android中的网络通信(一) socket编程
- Android中基于Socket的网络通信
- 34、Android中基于Socket的网络通信(一)
- Android入门笔记 - 网络通信 - Socket
- Android 网络通信之Socket
- Android中基于TCP协议的网络通信之使用Socket进行通信
- Android网络通信Socket使用
- Android网络通信之Socket
- Android网络编程实践之旅(二):基于Socket的网络通信
- Android网络开发之Socket通信
- Android开发手记:Socket网络通信
- Android中基于TCP协议的网络通信之使用Socket进行通信
- android网络通信之socket编程
- Android网络编程实践之旅(二):基于Socket的网络通信 .
- Android Socket网络通信