转载请注明出处: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是不一样的。
- 客户端:可以连接服务端、发送数据、接收数据、关闭连接等。
- 服务端:可以实现绑定绑定端口,接收客户端的连接、接收数据,发送数据等。
先看下效果图:
文章图片
文章图片
文章图片
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,则可以使用任意地址。 -
步骤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通信的使用基本就完成了,最后看一下图片,更容易理解其通信机制。
文章图片
推荐阅读
- Linux|Linux--网络基础
- 工具|Wireshark抓包对其字TCP段理解
- 面试|【全网最全】计算机网络笔试面试(八股文)
- 网络|《TCP-IP协议族》(第4版)PDF高清电子版——网盘下载
- TCP/IP|TCP/IP 四层模型
- ARP缓存表更新条件
- TCP/IP协议簇
- TCP|TCP/UDP协议
- Linux|利用tcpip堆栈处理不同判断远程操作系统. ..