Android 网络编程 TCP(聊天实现)看这一篇就够了

先补充一下什么是tcp

        TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。它是互联网协议套件(TCP/IP)中的一部分,用于在网络中的计算机之间进行可靠的数据传输。

以下是 TCP 的一些主要特点和概念:

面向连接: 在使用 TCP 进行通信时,通信的两端需要先建立连接,然后才能进行数据的传输。连接建立后,双方可以通过这个连接进行数据的可靠传输。

可靠性: TCP 提供可靠的数据传输,确保数据的完整性和顺序性。它使用确认和重传机制来检测丢失的数据包并进行重传,以确保数据的可靠性。

全双工通信: TCP 支持全双工通信,允许双方在同一时间既能发送数据也能接收数据。这使得双方可以同时进行双向的交互。

流控制: TCP 使用流控制机制来防止发送方发送过多的数据导致接收方无法处理。通过通告窗口大小,TCP 可以动态调整发送方的发送速率。

拥塞控制: TCP 通过拥塞控制机制来避免网络拥塞。通过调整发送速率和使用慢启动等算法,TCP 可以适应网络的变化,并减少拥塞的发生。

面向字节流: TCP 是面向字节流的协议,它将数据视为字节流而不是消息。因此,发送的数据可能会被分割成小块进行传输,而接收方需要重新组装这些数据。

三次握手和四次挥手: 在建立连接时,使用三次握手协议(SYN,SYN-ACK,ACK)来确保双方都准备好进行通信。在关闭连接时,使用四次挥手协议来优雅地关闭连接。

接着是示例核心代码(有大白话注释)

服务端

public class TcpServer2 {

    private static final String TAG = "TcpServer2";
    private final int mPort;
    private final Handler mHandler;
    private ServerSocket mServerSocket;
    private Socket mClientSocket;

     /**
      *  @description 构造函数 port:监听的端口  handler:用来更新ui
      */
    public TcpServer2(int port, Handler handler) {
        this.mPort = port;
        this.mHandler = handler;
    }

    /**
     * @description 开启连接线程
     */
    public void startThread() {
        ThreadPoolManager.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    //监听端口
                    mServerSocket = new ServerSocket(mPort);
                    MlogUtil.d(TAG, "server: 开始监听客户端连接 ");
                    //持续监听 实现持续聊天
                    while (true) {
                        //监听时候会堵塞
                        mClientSocket = mServerSocket.accept();
                        MlogUtil.d(TAG, "server: 客户端连接 ");
                        //在子线程里进行读取数据
                        readClientMsg();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

     /**
      *  @description 读取数据
      */
    private void readClientMsg() {
        //在子线程里进行读取数据
        ThreadPoolManager.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    //获取输入流
                    InputStream inputStream = mClientSocket.getInputStream();
                    DataInputStream dataInputStream = new DataInputStream(inputStream);
                    byte[] buf = new byte[1024];
                    int read = dataInputStream.read(buf);
                    //知道读取到数据
                    while ((read = dataInputStream.read(buf)) > 0) {
                        String data = new String(buf, 0, read, "utf-8");
                        //去显示
                        Message message = new Message();
                        message.obj = data;
                        message.what = Constants.TCP_SERVER_WHAT;
                        mHandler.sendMessage(message);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

     /**
      *  @description 发送数据
      */
     public void sendData(final String str) {
         ThreadPoolManager.getInstance().execute(new Runnable() {
             @Override
             public void run() {
                 try {
                     //获取输出流
                     OutputStream outputStream = mClientSocket.getOutputStream();
                     DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
                     dataOutputStream.write(str.getBytes());
                     dataOutputStream.flush();
                     /*PrintWriter printWriter = new PrintWriter(outputStream, true);
                     printWriter.println(str);
                     printWriter.flush();*/
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         });
     }

     /**
      *  @description 释放资源
      */
     public void release()  {
         try {
             if (mClientSocket != null) {
                 mClientSocket.close();
             }
             if (mServerSocket != null) {
                 mServerSocket.close();
             }
         } catch (IOException e) {
             e.printStackTrace();
         }

     }
}

使用

  //启动服务 监听端口
  tcpServer = new TcpServer2(Constants.TCP_PORT,mHandel);
  //建立连接
  if (tcpServer != null) {
      tcpServer.startThread();
  }            
           

客户端

public class TcpClient2 {
    private static final String TAG = "TcpClient2";
    private final String ip;
    private final int mPort;
    private final Handler mHandler;
    private Socket mSocket;

    public TcpClient2(String ip, int port, Handler handler) {
        this.ip = ip;
        this.mPort = port;
        this.mHandler = handler;
    }
     /**
      *  @description 开始连接服务端
      */
     public void  connectServer () {
         ThreadPoolManager.getInstance().execute(new Runnable() {
             @Override
             public void run() {
                 //连接指定服务器
                 try {
                     MlogUtil.d(TAG, "client:连接服务器 ");
                     mSocket = new Socket(ip, mPort);
                     MlogUtil.d(TAG, "client:连接服务器成功 ");
                     //读取数据
                     readData();
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         });
     }

      /**
       *  @description
       */
    private void readData() {
        //在其他线程读取数据
        ThreadPoolManager.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    DataInputStream stream = null;
                    try {
                        InputStream inputStream = mSocket.getInputStream();
                        stream = new DataInputStream(inputStream);
                        byte[] buf = new byte[1024];
                        int read = stream.read(buf);
                        while ((read = stream.read(buf)) > 0) {
                            String data = new String(buf, 0, read, "utf-8");
                            //更新ui
                            Message message = new Message();
                            message.obj = data;
                            message.what = Constants.TCP_CLIENT_WHAT;
                            mHandler.sendMessage(message);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        //释放资源
                        try {
                            if (stream != null) {
                                stream.close();
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
    }
     /**
      *  @description 发送数据
      */
     public void sendData(final String str) {
         ThreadPoolManager.getInstance().execute(new Runnable() {
             @Override
             public void run() {
                 try {
                     OutputStream outputStream = mSocket.getOutputStream();
                     DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
                     dataOutputStream.write(str.getBytes());
                     dataOutputStream.flush();
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         });
     }

      /**
       *  @description 释放资源
       */
    public void release() {
        if (mSocket != null) {
            try {
                mSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

使用

 //开始连接服务器
            tcpClient = new TcpClient2(ip,Constants.TCP_PORT,mHandel);
            tcpClient.connectServer();

TCP和UDP对比

连接性:

TCP: 面向连接。在通信前,必须经过三次握手建立连接,之后才能进行数据传输。连接是可靠的,确保数据的完整性和顺序性。
UDP: 无连接。通信时无需建立连接,直接发送数据包。UDP是一种无连接、不可靠的协议,不保证数据的可靠性和顺序性。
可靠性:

TCP: 提供可靠的数据传输。通过确认和重传机制,TCP确保数据的完整性,丢失的数据会被重传,确保数据的正确性。
UDP: 不提供可靠性保证。数据发送后,UDP不会确认是否到达,也不会重传丢失的数据包。适用于实时性要求较高的场景,如音视频传输。
顺序性:

TCP: 保证数据的顺序性。数据按照发送顺序在接收端被重新组装。
UDP: 不保证数据的顺序性。发送的数据包可能以不同的顺序到达接收端。
流量控制:

TCP: 提供流量控制机制,通过通告窗口大小调整发送方的发送速率,防止发送方发送过多数据导致接收方不堪重负。
UDP: 无流量控制机制。发送方不会考虑接收方的处理能力,可能导致数据包的丢失。
拥塞控制:

TCP: 提供拥塞控制机制,通过慢启动等算法调整发送速率,适应网络拥塞。
UDP: 无拥塞控制机制。发送方会不加限制地发送数据,可能导致网络拥塞。
适用场景:

TCP: 适用于要求可靠性和有序性的应用,如文件传输、网页浏览、电子邮件等。
UDP: 适用于实时性要求较高、容忍数据丢失的应用,如实时音视频传输、在线游戏等。
头部开销:

TCP: 头部较大,有连接建立和维护的开销。
UDP: 头部较小,无连接的开销较小。
总体而言,TCP和UDP各有优劣,选择使用哪种协议取决于应用的具体需求。如果对数据的可靠性和有序性要求较高,通常选择TCP。如果对实时性要求较高,而对数据的可靠性和顺序性要求较低,可以选择UDP。

  • 16
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码划云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值