TCP|Android上TCP通信实现

转载请注明出处:http://blog.csdn.net/vnanyesheshou/article/details/74896575
之前做过的一个局域网内TCP通信、聊天的demo(当然不是局域网也可以进行通信,刚试了一下可以的),周日整理了一下。该demo可以做客户端,也可以做服务端。两个手机都安装该应用,一个做客户端、一个做服务端,然后进行通信(连接在同一局域网,或服务器是外网ip,客户端可以上网)。
20180728修改:Android7.0以上socket发送数据失败,需要将发送的操作放到子线程中,最新demo以更新。
demo下载地址:http://www.demodashi.com/demo/10567.html
1 简介 TCP(Transmission Control Protocol):传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。

在Internet协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。
Socket 英文原义是“孔”或“插座”。通常称为”套接字”,用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务(客户若是需要哪种服务,就讲插头连到相应的插座上),客户的“插头”也是一个socket。
Socket通信,需要服务端和客户端,两端都要实例化一个Socket。但服务器和客户端的Socket是不一样的。
  • 客户端:可以连接服务端、发送数据、接收数据、关闭连接等。
  • 服务端:可以实现绑定绑定端口,接收客户端的连接、接收数据,发送数据等。
Android在包java.net包下提供了ServerSocketSocket类,ServerSocket用于创建服务器的Socket。Socket用于实例化客户端的Socket。当连接成功,客户端和服务端都会产生一个Socket实例,通过此Socket进行通信。
先看下效果图:
TCP|Android上TCP通信实现
文章图片

TCP|Android上TCP通信实现
文章图片
TCP|Android上TCP通信实现
文章图片

2 服务端 服务端ServerSocket的构造方法有以下几种:
  • ServerSocket ():构造一个新的未绑定的ServerSocket。
  • ServerSocket (int port):构造一个新的ServerSocket并绑定到指定端口,如果port等于0,则端口由系统自动分配。
  • ServerSocket (int port, int backlog):构造一个新的ServerSocket并绑定到指定端口,并指定进入队列的数目。如果port等于0,则端口由系统自动分配。
  • ServerSocket (int port, int backlog, InetAddress localAddress):构造一个新的ServerSocket并绑定到指定端口和指定的地址,并指定进入队列的数目。如果port等于0,则端口由系统自动分配。如果localAddress为null,则可以使用任意地址。
  • -
TCP服务端工作具体步骤:
步骤1:创建一个ServerSocket,并绑定到指定端口上。
try { //开启服务、指定端口号 ServerSocket mServerSocket = new ServerSocket(5566); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "服务开启失败", Toast.LENGTH_SHORT).show(); return; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

步骤2:调用ServerSocket的accept(),监听连接请求,如果客户端请求连接,则接收连接,返回Scoekt对象。
Socket mSocket = mServerSocket.accept();
步骤3:调用Socket类的getInputStream()和getOutputStream()获取输入输出流。
class SocketAcceptThread extends Thread{ @Override public void run() { try { //等待客户端的连接,Accept会阻塞,直到建立连接, //所以需要放在子线程中运行。 mSocket = mServerSocket.accept(); //获取输入流 mInStream = mSocket.getInputStream(); //获取输出流 mOutStream = mSocket.getOutputStream(); } catch (IOException e) { e.printStackTrace(); mHandler.sendEmptyMessage(MSG_SOCKET_ACCEPTFAIL); return; } Log.i(TAG, "accept success"); mHandler.sendEmptyMessage(MSG_SOCKET_CONNECT); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

步骤4:开始发送、接收数据。
发送数据:
private void writeMsg(String msg){ if(msg.length() == 0 || mOutStream == null) return; try {//发送 mOutStream.write(msg.getBytes()); mOutStream.flush(); }catch (Exception e) { e.printStackTrace(); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

接收数据:(从输入流读取数据,需要在一个子线程中循环运行下面的方法。)
byte[] buffer = new byte[1024]; //循环执行read,用来接收数据。 //数据存在buffer中,count为读取到的数据长度。 int count = mInStream.read(buffer);
  • 1
  • 2
  • 3
  • 4
  • 5

步骤5:服务不再需要,则关闭服务。
if(mServerSocket != null){ try { mServerSocket.close(); } catch (IOException e) { e.printStackTrace(); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3 客户端 TCP客户端工作具体步骤:
步骤1:创建一个Socket,连接到服务器端、指定端口号。放在子线程中运行,否则会有问题。
class SocketConnectThread extends Thread{ public void run(){ try { //指定ip地址和端口号 mSocket = new Socket(mIpAddress,mClientPort); if(mSocket != null){ //获取输出流、输入流 mOutStream = mSocket.getOutputStream(); mInStream = mSocket.getInputStream(); } } catch (Exception e) { e.printStackTrace(); mHandler.sendEmptyMessage(MSG_SOCKET_CONNECTFAIL); return; } Log.i(TAG,"connect success"); mHandler.sendEmptyMessage(MSG_SOCKET_CONNECT); }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

步骤2:调用Socket类的getInputStream()和getOutputStream()获取输入输出流。
具体代码如上所示。
步骤3:发送、接收数据。(发送接收数据与服务端方法相同。)
发送数据:
private void writeMsg(String msg){ if(msg.length() == 0 || mOutStream == null) return; try {//发送 mOutStream.write(msg.getBytes()); mOutStream.flush(); }catch (Exception e) { e.printStackTrace(); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

接收数据:(从输入流读取数据,需要在一个子线程中循环运行下面的方法。)
byte[] buffer = new byte[1024]; //循环执行read,用来接收数据。 //数据存在buffer中,count为读取到的数据长度。 int count = mInStream.read(buffer);
  • 1
  • 2
  • 3
  • 4

步骤4:关闭Socket
public void closeConnection(){ try { if (mOutStream != null) { mOutStream.close(); //关闭输出流 mOutStream = null; } if (mInStream != null) { mInStream.close(); //关闭输入流 mInStream = null; } if(mSocket != null){ mSocket.close(); //关闭socket mSocket = null; } } catch (IOException e) { e.printStackTrace(); } if(mReceiveThread != null){ mReceiveThread.threadExit(); mReceiveThread = null; } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

4 总结 【TCP|Android上TCP通信实现】在清单文件中添加权限
  • 1

TCP通信的使用基本就完成了,最后看一下图片,更容易理解其通信机制。
TCP|Android上TCP通信实现
文章图片

    推荐阅读