美文网首页
Android TCP/IP网络编程Socket通信实现Demo

Android TCP/IP网络编程Socket通信实现Demo

作者: Crazy程序猿 | 来源:发表于2021-03-13 14:17 被阅读0次

    本文主要讲解安卓(Android)TCP Socket通讯客户端(Client)和服务器(Server)Demo的实现(附源码),要注意BufferedReader的readLine()方法【((line = br.readLine()) != null)】 的阻塞问题,以及对接硬件的项目数据在十六进制&&byte&&int的转换处理。

    大坑

    最近有个项目需要用到TCP Socket通讯,遇到了一个大坑,所以做了这个Demo。
    读取socket输入流的时候很多代码都会这么写,一般也不会有什么问题,但是readLine()方法读取不到换行和回车时会阻塞!
    String line = null;
    while ((line = br.readLine()) != null) {
    }
    readLine()是个阻塞函数,可以点进去查看源码,只有遇到换行或者回车回车符(’\n’,’\r’ 对应十六进制是 0D 0A)才会返回,而有些模块返回给你的数据不带这两个结束符,所以导致阻塞,程序不能走下去。这种情况一般如果模块那边愿意修改加上结束符,那就没问题。如果模块那边又不方便改,那就不能用这种方式了,得换种写法。

    调试工具

    调试的实时我们可以借助一些PC端的工具,TCP调试助手、TCP测试工具类似的,度娘下很多,操作也是傻瓜式的,填写IP和端口然后建立或者连接。


    在这里插入图片描述
    image

    Demo演示及实现

    废话少说,直接 进入今天的主题,下面就看看如何在Android上利用TCP/IP协议使用Socket与Server进行通讯吧!


    tcpdemo.gif

    一、权限

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

    二、服务端实现,简单来说就3步

    1、 创建ServerSocket ,监听端口,等待客户端Socket连接
    2、从Socket里获取的客户端发来的消息
    3、通过Socket给客户端发消息

    核心代码如下

    class ServerSocketThread extends Thread {
    
        @Override
        public void run() {
            try {  
               // 创建ServerSocket  
               ServerSocket serverSocket = new ServerSocket(9999);  
               System.out.println("--开启服务器,监听端口 9999--");  
     
               // 监听端口,等待客户端连接  
               while (true) {  
                   System.out.println("--等待客户端连接--");  
                   Socket socket = serverSocket.accept(); //等待客户端连接  
                   System.out.println("得到客户端连接:" + socket);  
                     
                   startReader(socket);  
               }  
     
           } catch (IOException e) {  
               e.printStackTrace();  
           } 
        }
    }
    
       /**  
        * 从参数的Socket里获取消息 
        */  
       private static void startReader(final Socket mSocket) {  
           new Thread(){  
               @Override  
               public void run() {  
                   try {  
                       // 获取读取流  
                       BufferedReader in = new BufferedReader(new InputStreamReader(mSocket.getInputStream(),"utf-8"))
                       String line="";
                       while ((line = in.readLine()) != null) {// 读取数据  
                           System.out.println("*等待客户端输入*");  
                           System.out.println("获取到客户端的信息:" + line);
                        }
                   } catch (IOException e) {  
                       e.printStackTrace();  
                   }  
               }  
           }.start();  
       } 
    
     //通过socket来给客户端发送消息
     private void serverSendMessage(String mServerSendMessage) {
         new Thread() {
             @Override
             public void run() {
                 PrintWriter out;
                 try {
                     out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream())), true);
                     out.println(mServerSendMessage);
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         }.start();
      }
    

    三、客户端实现,跟服务器端流程类似

    1、与服务器建立Socket连接
    2、获取到输入输出流
    3、收/发送消息

    //与服务器建立连接
    Socket mClientSocket = new Socket(mClientIp, mClientPort);
    
    //从socket获取输入输出流
    BufferedReader mClientIn = new BufferedReader(new InputStreamReader(mClientSocket.getInputStream()));
    PrintWriter mClientOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mClientSocket.getOutputStream())), true);
    
    //监听服务端下发的消息
    String clientReceiverMessage;
    if ((clientReceiverMessage = mClientIn.readLine()) != null) {
        if (mOnConnectListener != null) {
            mOnConnectListener.onMessage(clientReceiverMessage);
        }
    } 
    
    //给服务端发消息
    mClientOut.println(mClientSendMessage);
    
    

    代码封装Listener接口

    在实际开发过程中,我们一般会把Socket这块封装起来,然后对外设置Listener接口,在其它模块里处理业务逻辑,也有的需要处理多个socket连接和通讯,

    服务器端代码实现示例

    public class TcpServer {
    
        private static final String TAG = "TcpServer";
    
        private static TcpServer mTcpServer = new TcpServer();
        private OnListener mOnListener;
        private ServerSocketThread mServerSocketThread;
    
        public static TcpServer getInstance() {
            return mTcpServer;
        }
    
        public void setOnListener(OnListener onListener) {
            mOnListener = onListener;
        }
    
        public interface OnListener {
            void onStart();
    
            void onNewClient(String serverIp, String clientIp, int count);
    
            void onError(Throwable e, String message);
    
            void onMessage(String ip, String message);
    
            void onAutoReplyMessage(String ip, String message);
    
            void onClientDisConnect(String ip);
    
            void onConnectTimeOut(String ip);
        }
    
        public void setPort(int port) {
            mServerPort = port;
        }
        
        ………………………………
        ………………………………
        ………………………………
    }
    

    十六进制收发处理

    对接硬件的项目通讯协议有可能是用十六进制的,所以数据要在字符串\byte\int 十六进制转换,不过通讯部分本质一样,代码如下

      //十六进制 发送
      try {
          //byte[] msg = {(byte) 0xaa,(byte) 0xbb,(byte) 0x0d,(byte) 0x0a};
          byte[] msg = IntByteStringHexUtil.hexStrToByteArray("AABB0D0A");
          OutputStream socketWriter = socket.getOutputStream();
    
          socketWriter.write(msg);
      } catch (IOException e) {
          e.printStackTrace();
      }
    
      //十六进制 接收
      InputStream socketReader = socket.getInputStream();
      byte buf[] = new byte[1024];
      int len = socketReader.read(buf);
    
      byte data[] = new byte[len];
      System.arraycopy(buf, 0, data, 0, len);
    
      logClient(len+","+IntByteStringHexUtil.byteArrayToHexStr(data));
    

    Demo源码下载地址

    源码也都放在CSDN上了,有需要的可以借鉴

    ===> Android TCP Socket通信实例Demo源码Apk下载

    相关文章

      网友评论

          本文标题:Android TCP/IP网络编程Socket通信实现Demo

          本文链接:https://www.haomeiwen.com/subject/uesxcltx.html