Socket实现java服务端与AndroidApp端数据交互
在这里主要想实现服务端向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端数据交互相关推荐
- java与c的交互,java与c/c++之间的数据交互,java交互
java与c/c++之间的数据交互,java交互 java与c/c++之间的数据交互有这样几种情况:java和c/c++之间基本数据类型的交互,java向c/c++传递对象类型,c/c++向java返 ...
- 【Linux】socket网络编程之服务器与客户端的数据交互
[Linux]socket网络编程之服务器与客户端的数据交互 前言参考 argc !=2是什么意思 inet pton函数 对stdin,stdout 和STDOUT_FILENO,STDIN_FIL ...
- java堆内与堆外数据交互_Java:汇总堆外数据
java堆内与堆外数据交互 探索如何以最小的垃圾回收影响和最大的内存利用率创建堆外聚合. 使用Java Map,List和Object创建大型聚合通常会产生大量堆内存开销. 这也意味着,一旦聚合超 ...
- java与c/c++之间的数据交互-----jni点滴
2019独角兽企业重金招聘Python工程师标准>>> 淡泊明志.宁静致远 A Diamond is just a piece of Coal that did well under ...
- 关于服务端与客户端的数据交互
一,数据交互 一般在于客户端显而易见的就是给客户展示数据的,而服务器端就是通过拿出数据库中的数据,再通过给数据做些整理,然后这些数据变成计算机能解析的语言,传递给客户端,然后客户端再将这些数据进行展示 ...
- Android 客户端Socket 与 Java服务端ServerSocket
Socket编程 一.Java网络编程基础知识 1.两台计算机间进行通讯需要以下三个条件: 1). IP地址(例如 : 192.168.1.1) 2). 协议(服务端与客户端之间双方自行 ...
- php udp发送和接收_63、php利用原生socket创建udp服务
1.案例函数汇总 2.案例 通过socket创建udp服务,获取对端的ip和port信息.并进行打印 2.1.udp服务源码 /** * Copyright(C) Iamasb * @project ...
- 如何使用Java与Mysql进行数据交互
ArthurSlog SLog-5 Year·1 Guangzhou·China July 11th 2018 微信扫描二维码,关注我的公众号 做到每个敲下的按键.每次鼠标的点击.每次手机屏幕的触碰, ...
- 图解Java服务端Socket建立原理
1.前言 1.1 目标 本文通过一个典型的java server socket代码,逐层剖析其tcp协议的服务端建立的原理,其中会涉及到linux内核的实现,本文会以简单通俗的图形将其中原理展示给大家 ...
最新文章
- JSP页面中使用JSTL标签出现无法解析问题解决办法
- 01-利用思维导图梳理JavaSE-Java语言基础
- Java程序员从笨鸟到菜鸟之(一百)sql注入攻击详解(一)sql注入原理详解
- linux date 小写h,linux date 命令详解[转载]
- 1.3 编程基础之算术表达式与顺序执行 04 带余除法
- 深入理解Yii2.0 (2)事件Event
- MYSQL 大数据性能优化
- 学数学建模算法对计算机的好处,浅议数学建模与算法
- win10电脑防火墙在哪里设置
- 玩家浅谈MID平板电脑主流中端方案
- 魔方优化大师 v5.15 中文绿色版
- mysql创建子用户代码_mysql创设用户及受权
- 深度学习相关的硬件配置
- 前端 html 文字在 div 中怎么实现自动换行
- Realsense L515使用
- 计算机单片机实训报告,单片机实训总结
- 自己的电脑出现在别人的电脑的网络位置中
- 怎样区别交换机、路由器和猫
- ec2远程mysql_从远程服务器连接到Amazon EC2上的mysql
- 抖音下播倒计时自动化软件,送礼物自动加时长