在这里主要想实现服务端向App端推送消息,所以采用了Socket。

java端:

第一步:创建ServerSocketManager.java类,这个类是针对客户端和App端的连接和断开进行监听,读取并发送数据这几个功能的封装,具体代码如下:

public class ServerSocketManager { //ServerSocketManager.java开始

private static ServerSocketManager manager;
 // 存储客户端ip-SocketChannel
 private static Map<String, SocketChannel> map;
 // 连接监听
 private static SelectorLoop connectionBell;
 // 读取监听
 private static List<SelectorLoop> readBells;
 private ServerSocketChannel ssc;
 // 标识是否已经开启读取客户端数据的线程
 public boolean isReadBellRunning = false;
 // 客户端连接断开监听
 private List<OnClientListener> clientListeners;
 // 接收客户端信息监听
 private List<OnReceivedMessageListener> messageListeners;

public void addOnClientListener(OnClientListener clientListener) {
  if (!this.clientListeners.contains(clientListener)) {
   this.clientListeners.add(clientListener);
  }
 }

public void removeClientListener(OnClientListener clientListener) {
  this.clientListeners.remove(clientListener);
 }

public void addOnReveicedMessageListener(
   OnReceivedMessageListener messageListener) {
  if (!this.messageListeners.contains(messageListener)) {
   this.messageListeners.add(messageListener);
  }
 }

public void removeOnReveicedMessageListener(
   OnReceivedMessageListener messageListener) {
  this.messageListeners.remove(messageListener);
 }

private ServerSocketManager() {
  map = new HashMap<String, SocketChannel>();
  clientListeners = new LinkedList<OnClientListener>();
  messageListeners = new LinkedList<ServerSocketManager.OnReceivedMessageListener>();
 }

public synchronized static ServerSocketManager getInstance() {
  if (manager == null) {
   manager = new ServerSocketManager();
  }
  return manager;
 }

public void startServer(String host, int port) throws IOException {
  System.out.println("-------ip-----" + host);
  readBells = new LinkedList<ServerSocketManager.SelectorLoop>();
  connectionBell = new SelectorLoop();
  // 开启一个server channel来监听
  ssc = ServerSocketChannel.open();
  // 开启非阻塞模式
  ssc.configureBlocking(false);
  ServerSocket socket = ssc.socket();
  socket.bind(new InetSocketAddress(host, port));
  // 给闹钟规定好要监听报告的事件,这个闹钟只监听新连接事件.
  ssc.register(connectionBell.getSelector(), SelectionKey.OP_ACCEPT);
  new Thread(connectionBell).start();
 }

public class SelectorLoop implements Runnable {
  private Selector selector;
  private ByteBuffer temp = ByteBuffer.allocate(1024);
  private boolean stop;
  private boolean using;

public boolean isUsing() {
   return using;
  }

public SelectorLoop() throws IOException {
   this.selector = Selector.open();
  }

public Selector getSelector() {
   return this.selector;
  }

public void stop() throws IOException {
   this.stop = true;
   if (this.selector.isOpen()) {
    this.selector.close();
    this.selector = null;
   }
  }

@Override
  public void run() {
   using = true;
   while (!stop) {
    System.out.println("-----------");
    try {
     // 阻塞,只有当至少一个注册的事件发生的时候才会继续.
     if (this.selector.select() > 0) {
      Set<SelectionKey> selectKeys = this.selector
        .selectedKeys();
      Iterator<SelectionKey> it = selectKeys.iterator();
      while (it.hasNext()) {
       SelectionKey key = it.next();
       it.remove();
       // 处理事件. 可以用多线程来处理.
       this.dispatch(key);
      }
     }
    } catch (IOException e) {
     e.printStackTrace();
    } catch (InterruptedException e) {
     e.printStackTrace();
    } catch (Exception e) {

}
   }
   stop = true;
  }

public void dispatch(SelectionKey key) throws IOException,
    InterruptedException {
   System.out.println("-----dispatch----------");
   // 测试此键的通道是否已准备好接受新的套接字连接。
   if (key.isAcceptable()) {
    System.out.println("-----isAcceptable----------");
    // 这是一个connection accept事件, 并且这个事件是注册在serversocketchannel上的.
    // 返回创建此键的通道
    ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
    // 接受一个连接.
    SocketChannel sc = ssc.accept();
    // 对新的连接的channel注册read事件. 使用readBell闹钟.
    sc.configureBlocking(false);
    SelectorLoop readBell = new SelectorLoop();
    readBells.add(readBell);
    sc.register(readBell.getSelector(), SelectionKey.OP_READ);
    String host = ((InetSocketAddress) sc.getRemoteAddress())
      .getHostString();

 int port=((InetSocketAddress) sc.getRemoteAddress()).getPort();//部署在外网时,需要获取随机的端口
    host=host+":"+port;
    // 存放连接的socket
    map.put(host, sc);
    if (!clientListeners.isEmpty()) {
     // 触发连接监听
     for (OnClientListener cl : clientListeners) {
      cl.onConnected(host);
     }
    }
    // 如果读取线程还没有启动,那就启动一个读取线程.
    // synchronized (ServerSocketManager.this) {
    // if (!ServerSocketManager.this.isReadBellRunning) {
    // ServerSocketManager.this.isReadBellRunning = true;
    new Thread(readBell).start();
    // }
    // }
   } else if (key.isReadable()) {
    // 这是一个read事件,并且这个事件是注册在socketchannel上的.
    SocketChannel sc = (SocketChannel) key.channel();
    String host = ((InetSocketAddress) sc.getRemoteAddress())
      .getHostString();

int port=((InetSocketAddress) sc.getRemoteAddress()).getPort();//部署在外网时,需要获取随机的端口
    host=host+":"+port;
    // 写数据到buffer
    int count = sc.read(temp);
    System.out.println("-------count-------" + count);
    if (count < 0) {
     map.remove(host);
     stop();
     if (!clientListeners.isEmpty()) {
      for (OnClientListener cl : clientListeners) {
       cl.onDisconnected(host);
      }
     }
     // 客户端已经断开连接.
     key.cancel();
     sc.close();
     return;
    }
    // 切换buffer到读状态,内部指针归位.
    temp.flip();
    String msg = Charset.forName("UTF-8").decode(temp).toString();
    // 清空buffer
    temp.clear();
    if (msg != null && !"".equals(msg)
      && !messageListeners.isEmpty()) {
     for (OnReceivedMessageListener rml : messageListeners) {
      rml.onReceivedMessage(host, msg);
     }
    }
   }
  }
 }

public void stop() {
  try {
   // if (readBell != null) {
   // readBell.stop();
   // }
   if (connectionBell != null) {
    connectionBell.stop();
   }
   if (ssc != null && ssc.isOpen()) {
    ssc.close();
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 }

/**
  * 发送信息
  *
  * @param host
  * @param msg
  * @throws IOException
  */
 public int sendMessage(String host, byte[] msg) throws IOException {
  System.out.println("host====" + host);
  SocketChannel sc = map.get(host);
  int retnum = 0;
  if (sc == null) {
   // System.out.println("--------发送失败,未找到对应的连接信息---------");
   return 0;
  }
  if (sc.isConnected()) {
   // echo back.
   sc.write(ByteBuffer.wrap(msg));
   retnum = 1;
  } else {
   System.out.println("---SocketChannel未开启--");
   retnum = -1;
  }
  return retnum;
 }

/**
  * 发送信息
  *
  * @param host
  * @param msg
  * @param charset
  * @throws IOException
  */
 public int sendMessage(String host, String msg, String charset)
   throws IOException {
  return sendMessage(host, msg.getBytes(charset));
 }

/**
  * 发送信息 charset default utf-8
  *
  * @param host
  * @param msg
  * @throws IOException
  */
 public int sendMessage(String host, String msg) throws IOException {
  return sendMessage(host, msg.getBytes("UTF-8"));
 }

/**
  * 监听客户端连接和断开
  *
  * @author YJH
  *
  */
 public interface OnClientListener {
  /**
   * 有客户端连接时调用
   *
   * @param host
   */
  void onConnected(String host);

/**
   * 有客户端断开连接时调用
   *
   * @param host
   */
  void onDisconnected(String host);
 }

/**
  * 监听客户端发送来的消息
  *
  * @author YJH
  *
  */
 public interface OnReceivedMessageListener {
  /**
   * 接收到消息
   *
   * @param host
   *            客户端ip
   * @param msg
   *            客户端信息
   */
  void onReceivedMessage(String host, String msg);
 }
} //ServerSocketManager.java结束

第二步:把方法封装完后,接下来,我们就可以在其它类里调用这些方法了,创建ServerSocketService.java类,代码如下:

@Service    //ServerSocketService.java开始
public class ServerSocketService {
 @Resource
 private FrameDao frameDao;

public void setFrameDao(FrameDao frameDao) {
  this.frameDao = frameDao;
 }

private ServerSocketManager manager;
 private OnClientListener clientListener = new OnClientListener() {

@Override
  public void onDisconnected(String host) {
   System.out.println("断开:" + host);

//断开连接时要做的操作写这里
  }

@Override
  public void onConnected(String host) {
   System.out.println("接入:" + host);
   //连接上时要做的操作写这里
  }
 };

private OnReceivedMessageListener messageListener = new OnReceivedMessageListener() {

@Override   //host是接入的ip,msg是接收到的信息
  public void onReceivedMessage(String host, String msg) {
   System.out.println("----msg--------" + msg);
   RequestData data = JSON.parseObject(msg,
     new TypeReference<RequestData>() {     //自定义的类:RequestData
     });
   Map<String, String> datamap = data.getData();
   String lightid = datamap.get("lightid");
   String projectname = datamap.get("projectname");
   String mac=datamap.get("mac");
   int act = data.getAct();// 操作id,是App端发送过来的值
   System.out.println(act + "----act---");
   switch (act) {
   case 1:
     //如果是操作标志是1的话进行的操作
    break;
   case 2:
     //如果是操作标志是2的话进行的操作
    break;

default:
    break;
   }

}
 };

{
  try {
   manager = ServerSocketManager.getInstance();
   manager.addOnClientListener(clientListener);
   manager.addOnReveicedMessageListener(messageListener);
   String ip = IP.getInstance().getAcceptIp();
   if (ip != null && !"".equals(ip)) {
    manager.startServer(ip, 9090);// ip是服务器的ip
    System.out.println("-------ServerSocketManager------");
   } else {
    System.out.println("-------读取ip配置失败------");
   }
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

public String sendMessage(String projectid, String light) {

//推送的信息一般是JSON类型,转换可以使用fastjson

 //获的要推送的信息frameInfo
   List<FrameInfo> frameInfo = frameDao.pushFrameInfo(
     Integer.parseInt(projectid), lights[i]);
   try {
    int num = manager.sendMessage(frameInfo.get(0).getIp(),
      JSON.toJSONString(frameInfo));
    if (num == 1) {
     msg = "推送成功";
    } else if (num == 0) {
     msg = "发送失败,未找到对应的连接信息";
    } else {
     msg = "Socket连接未开启";
    }
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  return msg;
 }

}  //ServerSocketService.java结束

第三步:创建RequestData.java类:

public class RequestData {
 private Integer act;//操作
 private Map<String, String> data;
 public Integer getAct() {
  return act;
 }
 public void setAct(Integer act) {
  this.act = act;
 }
 public Map<String, String> getData() {
  return data;
 }
 public void setData(Map<String, String> data) {
  this.data = data;
 }
 public RequestData() {
  super();
  // TODO Auto-generated constructor stub
 }
 public RequestData(Integer act, Map<String, String> data) {
  super();
  this.act = act;
  this.data = data;
 }
}

到此java服务器端完成,接下来android端

第一步:创建ClientManager.java类:

public class ClientManager {

    private static ClientManager manager;    private SocketChannel socketChannel;    private SelectorLoop readBell;    private OnConnectedListener connectedListener;    private OnReceivedMessageListener messageListener;    private ByteBuffer temp = ByteBuffer.allocate(1024);

    public void setOnReceivedMessageListener(OnReceivedMessageListener messageListener) {        this.messageListener = messageListener;    }

    public void setOnConnectedListener(OnConnectedListener connectedListener) {        this.connectedListener = connectedListener;    }

    private ClientManager() {    }

    public static ClientManager getInstance() {        if (manager == null) {            manager = new ClientManager();        }        return manager;    }

    public void sendMessage(String msg, String charset) {        sendMessage(msg.getBytes(Charset.forName(charset)));    }

    public void sendMessage(String msg) {        Log.e("aaa",msg+"--sendMessage---");        sendMessage(msg.getBytes(Charset.forName("UTF-8")));    }

    public void sendMessage(final byte[] msg) {        new Thread() {            @Override            public void run() {                try {                    if(socketChannel.isConnected()) {                        socketChannel.write(ByteBuffer.wrap(msg));                    }else{                        Log.e("aaaa","-------连接已断开------");                    }                } catch (IOException e) {                    e.printStackTrace();                }            }        }.start();    }

    public void start(final String host, final int port) {        new Thread() {            @Override            public void run() {                try {                    readBell = new SelectorLoop();                    // 连接远程server                    socketChannel = SocketChannel.open();                    boolean isConnected;                    while (true) {                        try {                            isConnected = socketChannel.connect(new InetSocketAddress(host, port));                            break;                        } catch (Exception e) {                            Thread.sleep(1000);                        }                    }                    socketChannel.configureBlocking(false);                    SelectionKey key = socketChannel.register(readBell.getSelector(), SelectionKey.OP_READ);                    if (isConnected) {                        if (connectedListener != null) {                            connectedListener.onConnected();                        }                    } else {                        key.interestOps(SelectionKey.OP_CONNECT);                    }                    new Thread(readBell).start();                } catch (IOException e) {                    e.printStackTrace();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }.start();    }

    class SelectorLoop implements Runnable {        private Selector selector;        private boolean stop;

        public SelectorLoop() throws IOException {            this.selector = Selector.open();        }

        public Selector getSelector() {            return this.selector;        }

        public void stop() throws IOException {            this.stop = true;            if (this.selector.isOpen()) {                this.selector.close();            }        }

        @Override        public void run() {            while (!stop) {                try {                    if (this.selector.select() > 0) {                        Log.e("aaaa", "--------有数据读取------");                        Set<SelectionKey> keys = this.selector.selectedKeys();                        Iterator<SelectionKey> it = keys.iterator();                        while (it.hasNext()) {                            SelectionKey key = it.next();                            it.remove();                            dispatchSelectionKey(key);                        }                    }                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }

    private void dispatchSelectionKey(SelectionKey key) throws IOException {        if (key.isConnectable()) {            // socket connected            SocketChannel sc = (SocketChannel) key.channel();            // 判断此通道上是否正在进行连接操作。            // 完成套接字通道的连接过程。            boolean f = sc.isConnectionPending();            if (f) {                boolean d = sc.finishConnect();                Log.e("aaaa", "=====finishConnect=====" + d);                if (d && connectedListener != null) {                    connectedListener.onConnected();                }            } else {                Log.e("aaaa", "连接已断开");                stop();            }        } else if (key.isReadable()) {            // msg received.            SocketChannel sc = (SocketChannel) key.channel();            int count = sc.read(temp);            if (count < 0) {//连接断开                stop();                return;            }            // 切换buffer到读状态,内部指针归位.            temp.flip();            String msg = Charset.forName("UTF-8").decode(temp).toString();            if (messageListener != null) {                messageListener.onReceivedMessage(msg);            }            // 清空buffer            temp.clear();        }    }

    public void stop() throws IOException {        if (connectedListener != null) {            connectedListener.onDisconnected();        }        readBell.stop();        if (socketChannel != null)            socketChannel.close();    }

    public interface OnConnectedListener {

        void onConnected();

        void onDisconnected();    }

    /**     * 监听客户端发送来的消息     *     * @author zz     */    public interface OnReceivedMessageListener {        /**         * 接收到消息         *         * @param msg 客户端信息         */        void onReceivedMessage(String msg);    }}

第二步:创建SocketService.java类:

public class SocketService {    private static ClientManager.OnConnectedListener connectedLis = new ClientManager.OnConnectedListener() {        @Override        public void onConnected() {            Log.e("aaaa", "-----Connected-----");            JSONObject jo = new JSONObject();            jo.put("act",1);            jo.put("data",App.getConfig());            ClientManager.getInstance().sendMessage(jo.toJSONString());        }

        @Override        public void onDisconnected() {            Log.e("aaaa", "-----Disconnected-----");        }    };

    private static ClientManager.OnReceivedMessageListener messageLis = new ClientManager.OnReceivedMessageListener() {        @Override        public void onReceivedMessage(String msg) {            Log.e("aaaa", "---msg----" + msg);            List<FrameInfo> infos = JSON.parseObject(msg, new TypeReference<List<FrameInfo>>() {            });            if (infos == null || infos.isEmpty())                return;            try {                ActiveAndroid.beginTransaction();                DBUtil.clearImageByType(1);                for (FrameInfo info : infos) {                    info.setReserve(1);                    info.save();                }                EventBus.getDefault().post(infos);                ActiveAndroid.setTransactionSuccessful();            } catch (Exception e) {                e.printStackTrace();            } finally {                ActiveAndroid.endTransaction();            }        }    };

    public static void startService(String host, String port) {        ClientManager manager = ClientManager.getInstance();        manager.setOnConnectedListener(connectedLis);        manager.setOnReceivedMessageListener(messageLis);        manager.start(host, Integer.parseInt(port));    }

    public static void stop() {        try {            ClientManager.getInstance().stop();        } catch (IOException e) {            e.printStackTrace();        }    }}第三步:在MainActivity.java类中调用开始方法
SocketService.startService("192.168.0.123","9090");
 

转载于:https://www.cnblogs.com/Sailsail/p/6612932.html

Socket实现java服务端与AndroidApp端数据交互相关推荐

  1. java与c的交互,java与c/c++之间的数据交互,java交互

    java与c/c++之间的数据交互,java交互 java与c/c++之间的数据交互有这样几种情况:java和c/c++之间基本数据类型的交互,java向c/c++传递对象类型,c/c++向java返 ...

  2. 【Linux】socket网络编程之服务器与客户端的数据交互

    [Linux]socket网络编程之服务器与客户端的数据交互 前言参考 argc !=2是什么意思 inet pton函数 对stdin,stdout 和STDOUT_FILENO,STDIN_FIL ...

  3. java堆内与堆外数据交互_Java:汇总堆外数据

    java堆内与堆外数据交互 探索如何以最小的垃圾回收影响和最大的内存利用率创建堆​​外聚合. 使用Java Map,List和Object创建大型聚合通常会产生大量堆内存开销. 这也意味着,一旦聚合超 ...

  4. java与c/c++之间的数据交互-----jni点滴

    2019独角兽企业重金招聘Python工程师标准>>> 淡泊明志.宁静致远 A Diamond is just a piece of Coal that did well under ...

  5. 关于服务端与客户端的数据交互

    一,数据交互 一般在于客户端显而易见的就是给客户展示数据的,而服务器端就是通过拿出数据库中的数据,再通过给数据做些整理,然后这些数据变成计算机能解析的语言,传递给客户端,然后客户端再将这些数据进行展示 ...

  6. Android 客户端Socket 与 Java服务端ServerSocket

    Socket编程 一.Java网络编程基础知识        1.两台计算机间进行通讯需要以下三个条件: 1). IP地址(例如 : 192.168.1.1) 2). 协议(服务端与客户端之间双方自行 ...

  7. php udp发送和接收_63、php利用原生socket创建udp服务

    1.案例函数汇总 2.案例 通过socket创建udp服务,获取对端的ip和port信息.并进行打印 2.1.udp服务源码 /** * Copyright(C) Iamasb * @project ...

  8. 如何使用Java与Mysql进行数据交互

    ArthurSlog SLog-5 Year·1 Guangzhou·China July 11th 2018 微信扫描二维码,关注我的公众号 做到每个敲下的按键.每次鼠标的点击.每次手机屏幕的触碰, ...

  9. 图解Java服务端Socket建立原理

    1.前言 1.1 目标 本文通过一个典型的java server socket代码,逐层剖析其tcp协议的服务端建立的原理,其中会涉及到linux内核的实现,本文会以简单通俗的图形将其中原理展示给大家 ...

最新文章

  1. JSP页面中使用JSTL标签出现无法解析问题解决办法
  2. 01-利用思维导图梳理JavaSE-Java语言基础
  3. Java程序员从笨鸟到菜鸟之(一百)sql注入攻击详解(一)sql注入原理详解
  4. linux date 小写h,linux date 命令详解[转载]
  5. 1.3 编程基础之算术表达式与顺序执行 04 带余除法
  6. 深入理解Yii2.0 (2)事件Event
  7. MYSQL 大数据性能优化
  8. 学数学建模算法对计算机的好处,浅议数学建模与算法
  9. win10电脑防火墙在哪里设置
  10. 玩家浅谈MID平板电脑主流中端方案
  11. 魔方优化大师 v5.15 中文绿色版
  12. mysql创建子用户代码_mysql创设用户及受权
  13. 深度学习相关的硬件配置
  14. 前端 html 文字在 div 中怎么实现自动换行
  15. Realsense L515使用
  16. 计算机单片机实训报告,单片机实训总结
  17. 自己的电脑出现在别人的电脑的网络位置中
  18. 怎样区别交换机、路由器和猫
  19. ec2远程mysql_从远程服务器连接到Amazon EC2上的mysql
  20. 抖音下播倒计时自动化软件,送礼物自动加时长

热门文章

  1. UA MATH571B 试验设计II 简单试验的分析方法
  2. VC++ 开发pop3收邮件程序的相关问题
  3. VC2019 使用GDI+ 显示PNG图片
  4. 文本和代码文件助手软件
  5. 配置tomcat8数据源(采用局部数据源方式)
  6. Linux操作系统报:read-only file system
  7. Flash学习笔记(01)
  8. hdu 2025:查找最大元素(水题,顺序查找)
  9. MyEclipse数据库连接配置(以Oracle为例)
  10. java动态代理上是否能再进行一层代理