在这里主要想实现服务端向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");