简单的Socket消息转发实现
来源:互联网 发布:怪医黑杰克 知乎 编辑:程序博客网 时间:2024/06/06 11:03
简单的Socket消息转发实现
闲来无事,就琢磨了一下socket;本节将实现一个简单的socket消息分发机制.功能比较简单,不喜勿喷.
现在成熟的消息分发有XMPP,MQTT等.分发协议参考JMS.
个人对MQTT比较熟悉.但是比较麻烦,用硬件设备实协议又要重新弄.所以就写个简单的搞下.
1.线程模型设计
程序线程模型如下图所示:
主线程分别开启子线程监听端口(这里只考虑同时连接一个设备和手机):
public static Executor executor; public static void main(String[] args) throws IOException { executor = Executors.newFixedThreadPool(4); executor.execute(new PhoneServer()); executor.execute(new DeviceServer()); while(true); }
这里采用了线程池执行任务,没测性能,不知道具体情况.请自行测试或修改为创建线程.
当有socket连接到服务端时开启新的任务去维护输出流.当前线程则一直读取输入流数据.
public class PhoneServer implements Runnable { ServerSocket phoneServer; Socket phone; public PhoneServer() throws IOException { super(); phoneServer = new ServerSocket(10001); } public void run() { phone = phoneServer.accept(); in = new BufferedReader(new InputStreamReader( phone.getInputStream())); out = new PrintWriter(phone.getOutputStream()); o = new PhoneOut(out); MainThread.executor.execute(o); ..... } }
2.消息分发
1.首先创建一个消息队列存放消息数据,这里为了方便就没有设计得更具体了.简单的搞一下
public class MessageEqueue extends Observable { private List mPhoneMessage; private List mDeviceMessage; private static MessageEqueue instance; public static MessageEqueue getInstance() { if (instance == null) { instance = new MessageEqueue(); } return instance; } /** * */ private MessageEqueue() { mPhoneMessage = new ArrayList(); mDeviceMessage = new ArrayList(); } ...... }
创建两个list分别存放两个客户端发来的消息,如果想设计得更好请封装成消息对象.
2.观察者模式.让消息序列继承Observable类,当有新消息添加时,通知观察者更新输出数据.创建一个ObserverAction类封装更新信息:
public class ObserverAction { public static final int ACTION_PHONE_UPDATE = 1; public static final int ACTION_DEVICE_UPDATE = 2; private int action; private String msg ; /** * @param action * @param msg */ public ObserverAction(int action, String msg) { super(); this.action = action; this.msg = msg; } /** * @return the msg */ public String getMsg() { return msg; } /** * @param msg the msg to set */ public void setMsg(String msg) { this.msg = msg; } /** * @param action */ public ObserverAction(int action) { super(); this.action = action; } /** * @return the action */ public int getAction() { return action; } /** * @param action * the action to set */ public void setAction(int action) { this.action = action; } /* (non-Javadoc) * @see java.lang.Object#toString() */ public String toString() { return "ObserverAction [action=" + action + ", msg=" + msg + "]"; } }
添加新消息时,通过notifyObservers()方法通知观察者.
public synchronized void addDeviceMessage(String msg) { mDeviceMessage.add(msg); setChanged(); notifyObservers(new ObserverAction(ObserverAction.ACTION_DEVICE_UPDATE, msg)); }
此处创建两个ACTION标记,来区分数据更新对象
public static final int ACTION_PHONE_UPDATE = 1;public static final int ACTION_DEVICE_UPDATE = 2;
3.读取消息
创建一个死循环来不断的接收客户端的消息,收到消息后添加到消息队列中,由输出任务向另一个客户端输出数据.
o = new PhoneOut(out); MainThread.executor.execute(o); MessageEqueue.getInstance().addObserver(o); while (true) { try { String str = in.readLine(); if (str != null) { if (str.equals("end")) break; MessageEqueue.getInstance().addDeviceMessage(str); } } catch (IOException e) { System.out.println(e.getMessage()); break; } }
4.输出消息.
前面提到创建一个新任务维护输出流,该任务没有消息时处于wait状态,当新消息到来时被唤醒.
public class PhoneOut implements Observer, Runnable { private PrintWriter out; private boolean isFinish = false; private Object wait = new Object(); /** * @param out */ public PhoneOut(PrintWriter out) { super(); this.out = out; } public void run() { while (!isFinish) { try { synchronized (wait) { String msg = null; while ((msg = MessageEqueue.getInstance() .getPhoneLastMessage()) != null) { out.println("device:" + msg); out.flush(); } wait.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("phone--end"); } /** * @return the isFinish */ public boolean isFinish() { return isFinish; } /** * @param isFinish * the isFinish to set */ public void setFinish(boolean isFinish) { this.isFinish = isFinish; synchronized (wait) { wait.notify(); } } public void update(Observable o, Object action) { ObserverAction a = (ObserverAction) action; if (a.getAction() == ObserverAction.ACTION_PHONE_UPDATE) { // out.println("device:" + a.getMsg()); // out.flush(); synchronized (wait) { wait.notify(); } } // if() } }
观察者更新时会调用update(Observable o, Object action)方法来更新观察者的状态.
synchronized (wait) { String msg = null; while ((msg = MessageEqueue.getInstance() .getPhoneLastMessage()) != null) { out.println("device:" + msg); out.flush(); } wait.wait(); }
当消息队列中的消息被发送完之后,任务会进入wait状态,直到下一次被新消息唤醒.
总结
在监听任务中,为了重复监听,在run()方法中添加一个死循环来实现接受下一次的socket连接.
while (true) { phone = phoneServer.accept(); System.out.println("PhoneServer.accept()"); in = new BufferedReader(new InputStreamReader( phone.getInputStream())); out = new PrintWriter(phone.getOutputStream()); o = new PhoneOut(out); ...... phone.close(); o.setFinish(true); phone = null; in = null; out = null; o = null; }
在关闭socket之后要清除以前的对象引用,以及消息队列中的消息,避免消息错误.
附上源码:源码下载地址
- 简单的Socket消息转发实现
- Flex的简单消息转发
- Flex的简单消息转发--逻辑
- 一个简单的Socket消息转发程序中使用ThreadPool和不使用的性能比对
- iOS中消息转发的实现
- 在 OC 中实现消息的转发
- PHP实现Socket侦听消息简单示例
- UDP实现内网到网的点对点发送消息与转发消息
- Socket的简单实现
- 数据链路层转发的简单实现
- OC的消息转发
- 利用OC的消息转发机制实现多重代理
- iOS的动态创建实例方法和实现消息转发
- Socket编程实现简单的服务器与客户端互发消息
- java socket client简单的检测断开并重连发送队列消息实现
- Java Socket发送与接收HTTP消息简单实现
- Java Socket发送与接收HTTP消息简单实现
- Java Socket发送与接收HTTP消息简单实现
- JAVA的Date类与Calendar类【转】
- yii2 i18n
- 使用Xcode和Instruments调试解决iOS内存泄露
- php获取客户端ip和服务器端ip
- C# UDP编程(通过类UdpClient实现收发)
- 简单的Socket消息转发实现
- 深入探究frame和bounds的区别以及setbounds使用
- 【jstl&el】jstl和EL的区别和使用
- ThreadLocal遇到线程池时, 各线程间的数据会互相干扰, 串来串去
- 使用NineOldAndroids 实现 Android ListView左右滑动删除效果
- 图片拉伸技巧
- iOS将image转90,180,270度的方法
- 【IOS 开发学习总结-OC-60】ipad应用开发的一些知识
- 单例模式