zoukankan      html  css  js  c++  java
  • Android中的socket本地通讯框架

    一、先分析Native层:

    1、C++基类SocketListener:

    1. class SocketListener {
    2.     int mSock;
    3.     const char *mSocketName;
    4.     SocketClientCollection *mClients;
    5.     pthread_mutex_t mClientsLock;
    6.     bool mListen;
    7.     int mCtrlPipe[2];
    8.     pthread_t mThread;
    9.  
    10. public:
    11.     SocketListener(const char *socketNames, bool listen);
    12.     SocketListener(int socketFd, bool listen);
    13.  
    14.     virtual ~SocketListener();
    15.     int startListener();
    16.     int stopListener();
    17.  
    18.     void sendBroadcast(int code, const char *msg, bool addErrno);
    19.     void sendBroadcast(const char *msg);
    20.  
    21. protected:
    22.     virtual bool onDataAvailable(SocketClient *c) = 0;
    23.  
    24. private:
    25.     static void *threadStart(void *obj);
    26.     void runListener();
    27. };
    28. #endif

    看关键接口runListener:

    1. void SocketListener::runListener() {
    2.  
    3.     while(1) {
    4.         SocketClientCollection::iterator it;
    5.         fd_set read_fds;
    6.         int rc = 0;
    7.         int max = 0;
    8.  
    9.         FD_ZERO(&read_fds);
    10.  
    11.         if (mListen) {
    12.             max = mSock;
    13.             FD_SET(mSock, &read_fds);
    14.         }
    15.  
    16.         FD_SET(mCtrlPipe[0], &read_fds);
    17.         if (mCtrlPipe[0] > max)
    18.             max = mCtrlPipe[0];
    19.  
    20.         pthread_mutex_lock(&mClientsLock);
    21.         for (it = mClients->begin(); it != mClients->end(); ++it) {
    22.             FD_SET((*it)->getSocket(), &read_fds);
    23.             if ((*it)->getSocket() > max)
    24.                 max = (*it)->getSocket();
    25.         }
    26.         pthread_mutex_unlock(&mClientsLock);
    27.  
    28.         if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
    29.             SLOGE("select failed (%s)", strerror(errno));
    30.             sleep(1);
    31.             continue;
    32.         } else if (!rc)
    33.             continue;
    34.  
    35.         if (FD_ISSET(mCtrlPipe[0], &read_fds))
    36.             break;
    37.         if (mListen && FD_ISSET(mSock, &read_fds)) {
    38.             struct sockaddr addr;
    39.             socklen_t alen = sizeof(addr);
    40.             int c;
    41.  
    42.             if ((c = accept(mSock, &addr, &alen)) < 0) {
    43.                 SLOGE("accept failed (%s)", strerror(errno));
    44.                 sleep(1);
    45.                 continue;
    46.             }
    47.             pthread_mutex_lock(&mClientsLock);
    48.             mClients->push_back(new SocketClient(c));
    49.             pthread_mutex_unlock(&mClientsLock);
    50.         }
    51.  
    52.         do {
    53.             pthread_mutex_lock(&mClientsLock);
    54.             for (it = mClients->begin(); it != mClients->end(); ++it) {
    55.                 int fd = (*it)->getSocket();
    56.                 if (FD_ISSET(fd, &read_fds)) {
    57.                     pthread_mutex_unlock(&mClientsLock);
    58.                     if (!onDataAvailable(*it)) {//由子类实现的接口。
    59.                         close(fd);
    60.                         pthread_mutex_lock(&mClientsLock);
    61.                         delete *it;
    62.                         it = mClients->erase(it);
    63.                         pthread_mutex_unlock(&mClientsLock);
    64.                     }
    65.                     FD_CLR(fd, &read_fds);
    66.                     continue;
    67.                 }
    68.             }
    69.             pthread_mutex_unlock(&mClientsLock);
    70.         } while (0);
    71.     }
    72. }

    2、他的第一继承者:

    1. #include "SocketListener.h"
    2. #include "FrameworkCommand.h"
    3.  
    4. class SocketClient;
    5.  
    6. class FrameworkListener : public SocketListener {
    7. public:
    8.     static const int CMD_ARGS_MAX = 16;
    9. private:
    10.     FrameworkCommandCollection *mCommands;
    11.  
    12. public:
    13.     FrameworkListener(const char *socketName);
    14.     virtual ~FrameworkListener() {}
    15.  
    16. protected:
    17.     void registerCmd(FrameworkCommand *cmd);
    18.     virtual bool onDataAvailable(SocketClient *c);
    19.  
    20. private:
    21.     void dispatchCommand(SocketClient *c, char *data);
    22. };

    他的onDataAvailable接口实现:

    1. bool FrameworkListener::onDataAvailable(SocketClient *c) {
    2.     char buffer[255];
    3.     int len;
    4.  
    5.     if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) {
    6.         SLOGE("read() failed (%s)", strerror(errno));
    7.         return errno;
    8.     } else if (!len)
    9.         return false;
    10.  
    11.     int offset = 0;
    12.     int i;
    13.  
    14.     for (i = 0; i < len; i++) {
    15.         if (buffer[i] == '') {
    16.             dispatchCommand(c, buffer + offset);
    17.             offset = i + 1;
    18.         }
    19.     }
    20.     return true;
    21. }

    3、实例:netd的CommandListener类:

    1. class CommandListener : public FrameworkListener {
    2.     static TetherController *sTetherCtrl;
    3.     static NatController *sNatCtrl;
    4.     static PppController *sPppCtrl;
    5.     static PanController *sPanCtrl;
    6.     static SoftapController *sSoftapCtrl;
    7.     static UsbController *sUsbCtrl;
    8.  
    9. public:
    10.     CommandListener();
    11.     virtual ~CommandListener() {}
    12.  
    13. private:
    14.  
    15.     static int readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx);
    16.  
    17.     class UsbCmd : public NetdCommand {
    18.     public:
    19.         UsbCmd();
    20.         virtual ~UsbCmd() {}
    21.         int runCommand(SocketClient *c, int argc, char ** argv);
    22.     };
    23.  
    24.     class SoftapCmd : public NetdCommand {
    25.     public:
    26.         SoftapCmd();
    27.         virtual ~SoftapCmd() {}
    28.         int runCommand(SocketClient *c, int argc, char ** argv);
    29.     };
    30.  
    31.     class InterfaceCmd : public NetdCommand {
    32.     public:
    33.         InterfaceCmd();
    34.         virtual ~InterfaceCmd() {}
    35.         int runCommand(SocketClient *c, int argc, char ** argv);
    36.     };
    37.  
    38.     class IpFwdCmd : public NetdCommand {
    39.     public:
    40.         IpFwdCmd();
    41.         virtual ~IpFwdCmd() {}
    42.         int runCommand(SocketClient *c, int argc, char ** argv);
    43.     };
    44.  
    45.     class TetherCmd : public NetdCommand {
    46.     public:
    47.         TetherCmd();
    48.         virtual ~TetherCmd() {}
    49.         int runCommand(SocketClient *c, int argc, char ** argv);
    50.     };
    51.  
    52.     class NatCmd : public NetdCommand {
    53.     public:
    54.         NatCmd();
    55.         virtual ~NatCmd() {}
    56.         int runCommand(SocketClient *c, int argc, char ** argv);
    57.     };
    58.  
    59.     class ListTtysCmd : public NetdCommand {
    60.     public:
    61.         ListTtysCmd();
    62.         virtual ~ListTtysCmd() {}
    63.         int runCommand(SocketClient *c, int argc, char ** argv);
    64.     };
    65.  
    66.     class PppdCmd : public NetdCommand {
    67.     public:
    68.         PppdCmd();
    69.         virtual ~PppdCmd() {}
    70.         int runCommand(SocketClient *c, int argc, char ** argv);
    71.     };
    72.  
    73.     class PanCmd : public NetdCommand {
    74.     public:
    75.         PanCmd();
    76.         virtual ~PanCmd() {}
    77.         int runCommand(SocketClient *c, int argc, char ** argv);
    78.     };
    79. };

    不能忘记NetdCommand类:

    1. #include <sysutils/FrameworkCommand.h>
    2.  
    3. class NetdCommand : public FrameworkCommand {
    4. public:
    5.     NetdCommand(const char *cmd);
    6.     virtual ~NetdCommand() {}
    7. };
    8. 4、分析一个子类ListTtysCmd:
    9. CommandListener::ListTtysCmd::ListTtysCmd() :
    10.                  NetdCommand("list_ttys") {
    11. }
    12.  
    13. int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
    14.                                              int argc, char **argv) {
    15.     TtyCollection *tlist = sPppCtrl->getTtyList();
    16.     TtyCollection::iterator it;
    17.  
    18.     for (it = tlist->begin(); it != tlist->end(); ++it) {
    19.         cli->sendMsg(ResponseCode::TtyListResult, *it, false);
    20.     }
    21.  
    22.     cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
    23.     return 0;
    24. }

    Java层:

    1. private void listenToSocket() throws IOException {
    2.     LocalSocket socket = null;
    3.  
    4.     try {
    5.         socket = new LocalSocket();
    6.         LocalSocketAddress address = new LocalSocketAddress(mSocket,
    7.                 LocalSocketAddress.Namespace.RESERVED);
    8.  
    9.         socket.connect(address);
    10.  
    11.         InputStream inputStream = socket.getInputStream();
    12.         mOutputStream = socket.getOutputStream();
    13.  
    14.         mCallbacks.onDaemonConnected();
    15.  
    16.         byte[] buffer = new byte[BUFFER_SIZE];
    17.         int start = 0;
    18.  
    19.         while (true) {
    20.             int count = inputStream.read(buffer, start, BUFFER_SIZE - start);
    21.             if (count < 0) break;
    22.  
    23.             // Add our starting point to the count and reset the start.
    24.             count += start;
    25.             start = 0;
    26.  
    27.             for (int i = 0; i < count; i++) {
    28.                 if (buffer[i] == 0) {
    29.                     String event = new String(buffer, start, i - start);
    30.                     if (LOCAL_LOGD) Slog.d(TAG, String.format("RCV <- {%s}", event));
    31.  
    32.                     String[] tokens = event.split(" ", 2);
    33.                     try {
    34.                         int code = Integer.parseInt(tokens[0]);
    35.  
    36.                         if (code >= ResponseCode.UnsolicitedInformational) {
    37.                             mCallbackHandler.sendMessage(
    38.                                     mCallbackHandler.obtainMessage(code, event));
    39.                         } else {
    40.                             try {
    41.                                 mResponseQueue.put(event);
    42.                             } catch (InterruptedException ex) {
    43.                                 Slog.e(TAG, "Failed to put response onto queue", ex);
    44.                             }
    45.                         }
    46.                     } catch (NumberFormatException nfe) {
    47.                         Slog.w(TAG, String.format("Bad msg (%s)", event));
    48.                     }
    49.                     start = i + 1;
    50.                 }
    51.             }
    52.  
    53.             // We should end at the amount we read. If not, compact then
    54.             // buffer and read again.
    55.             if (start != count) {
    56.                 final int remaining = BUFFER_SIZE - start;
    57.                 System.arraycopy(buffer, start, buffer, 0, remaining);
    58.                 start = remaining;
    59.             } else {
    60.                 start = 0;
    61.             }
    62.         }
    63.     } catch (IOException ex) {
    64.         Slog.e(TAG, "Communications error", ex);
    65.         throw ex;
    66.     } finally {
    67.         synchronized (mDaemonLock) {
    68.             if (mOutputStream != null) {
    69.                 try {
    70.                     mOutputStream.close();
    71.                 } catch (IOException e) {
    72.                     Slog.w(TAG, "Failed closing output stream", e);
    73.                 }
    74.                 mOutputStream = null;
    75.             }
    76.         }
    77.  
    78.         try {
    79.             if (socket != null) {
    80.                 socket.close();
    81.             }
    82.         } catch (IOException ex) {
    83.             Slog.w(TAG, "Failed closing socket", ex);
    84.         }
    85.     }
    86. }

    sendCommandLocked接口

    1. /**
    2.   * Sends a command to the daemon with a single argument
    3.   *
    4.   * @param command The command to send to the daemon
    5.   * @param argument The argument to send with the command (or null)
    6.   */
    7.  private void sendCommandLocked(String command, String argument)
    8.          throws NativeDaemonConnectorException {
    9.      if (command != null && command.indexOf('') >= 0) {
    10.          throw new IllegalArgumentException("unexpected command: " + command);
    11.      }
    12.      if (argument != null && argument.indexOf('') >= 0) {
    13.          throw new IllegalArgumentException("unexpected argument: " + argument);
    14.      }
    15.  
    16.      if (LOCAL_LOGD) Slog.d(TAG, String.format("SND -> {%s} {%s}", command, argument));
    17.      if (mOutputStream == null) {
    18.          Slog.e(TAG, "No connection to daemon", new IllegalStateException());
    19.          throw new NativeDaemonConnectorException("No output stream!");
    20.      } else {
    21.          StringBuilder builder = new StringBuilder(command);
    22.          if (argument != null) {
    23.              builder.append(argument);
    24.          }
    25.          builder.append('');
    26.  
    27.          try {
    28.              mOutputStream.write(builder.toString().getBytes());
    29.          } catch (IOException ex) {
    30.              Slog.e(TAG, "IOException in sendCommand", ex);
    31.          }
    32.      }
    33.  }

     

      

  • 相关阅读:
    基于网页的暖通空调监控方案
    基于SVG+AJAX的网页数据监控
    基于WebGL的三维的物联网平台技术
    Tomcat部署多个Springboot项目报错 InstanceNotFoundException: com.alibaba.druid:type=DruidDataSourceStat
    MYSQL 快速备份大数据量
    防止过度工程-[拒绝完美主义]
    ES6学习
    Linux系统上java调用C++ so库文件
    第二十四篇 -- Cache学习
    第二十八篇 -- 学习第五十一天打卡20190819
  • 原文地址:https://www.cnblogs.com/jevan/p/3148769.html
Copyright © 2011-2022 走看看