TCP|Android上TCP通信实现

版权声明:本文出自朋永的博客,转载必须注明出处。 https://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进行通信。
先看下效果图:
这里写图片描述
这里写图片描述 这里写图片描述


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 总结

在清单文件中添加权限

<uses-permission android:name="android.permission.INTERNET"/>
 
 
  • 1

TCP通信的使用基本就完成了,最后看一下图片,更容易理解其通信机制。
这里写图片描述

  • 8
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值