您的位置:首页 > 编程语言 > Java开发

使用OSGI写一个简单得Telnet聊天程序.(参考TutorialEclipseCon06)

2007-08-14 16:34 1121 查看
最近使用OSGI原理写一个简单得聊天程序.
首先新建一个equinox得Plugin.再创建一个接口:




public interface IChannel ...{


String CHANNEL_NAME = "channel.name";




void send(String form, String msg) throws IOException;


}

这个接口主要作用是一个频道发送信息.以此只定义了一个send方法.
再新建另一个equinox的Plugin,使用Component的方式创建一个OSGI-INF/telnet_component.xml.代码如下:


<?xml version="1.0" encoding="UTF-8"?>


<component name="Telenet_Component">


<implementation class="org.dengues.zos.chat.telnet.TelnetChatComponent"></implementation>


<reference name="LOG" interface="org.osgi.service.log.LogService"></reference>


</component>



这样一来它的实现类就是TelnetChatComponent.java: 它的代码如下:




public class TelnetChatComponent extends Thread ...{




protected LogService log;




protected boolean quite;




protected List<Handler> handlers = new ArrayList<Handler>();




protected ServerSocket server;




private ComponentContext context;






protected void activate(ComponentContext context) ...{


this.context = context;


log = (LogService) context.locateService("LOG");


log.log(LogService.LOG_INFO, "Component active!!!!!");


start();


}






protected void deactivate(ComponentContext context) throws Exception ...{


log.log(LogService.LOG_INFO, "Component deactive!!!!!");


quite = true;




for (Handler handler : handlers) ...{


handler.close();


}


server.close();


}




@Override




public void run() ...{


super.run();




while (!quite) ...{




try ...{


server = new ServerSocket(55555);


loop();




} catch (Exception e) ...{


log.log(LogService.LOG_ERROR, "[TelnetChat] Inner loop", e);


}


}


}






private void loop() throws Exception ...{




while (!quite) ...{




try ...{


Socket accept = server.accept();


Handler handler = new Handler(context.getBundleContext(),


accept, this);


handlers.add(handler);


handler.start();




} catch (Exception e) ...{


e.printStackTrace();


}


}


}






public void remove(IChannel channel) ...{


this.handlers.remove(channel);


}






protected void sleep(int ms) ...{




try ...{


Thread.sleep(ms);




} catch (Exception e) ...{


}


}




}

由于使用的Component在激活的时候会默认调用activate方法.这里为了记录激活日志.在记录日志之后.我们先新建一个ServerSocket端口是55555.另外还有一个类实现IChannel.就是Handler.java:




public class Handler extends Thread implements IChannel ...{


private BundleContext context;


private Socket socket;


private TelnetChatComponent component;




private PrintWriter writer;




private boolean quit;


private String user;


private IChannel channel;




public Handler(BundleContext context, Socket socket,




TelnetChatComponent component) throws Exception ...{


this.context = context;


this.socket = socket;


this.component = component;


writer = new PrintWriter(new OutputStreamWriter(socket


.getOutputStream()));


}




@Override




public void send(String form, String msg) throws IOException ...{


writer.println(form + " -> " + msg);


writer.flush();


}






public void close() ...{




try ...{


quit = true;


this.writer.close();


this.socket.close();




} catch (Exception e) ...{


e.printStackTrace();


}


}






public void run() ...{


super.run();


writer.println("Welcome... Chat!");


writer.print("Enter Name: ");


writer.flush();




try ...{


BufferedReader reader = new BufferedReader(new InputStreamReader(


socket.getInputStream()));


String line = "";




while (!quit && (line = reader.readLine()) != null) ...{


line = line.trim();


process(line);


}




} catch (Exception e) ...{




if (!quit) ...{


component.log.log(LogService.LOG_ERROR, "Reading User Name: ",


e);


}




} finally ...{




if(channel!=null) ...{


component.remove(channel);


}


}


}






private void process(String line) throws Exception ...{




if (user == null) ...{


user = line;


Hashtable<String, String> props = new Hashtable<String, String>();


props.put(CHANNEL_NAME, user);


channel = (IChannel) context.registerService(IChannel.class


.getName(), this, props);


send("info", "set User to" + user);




} else if (line.endsWith("/quit")) ...{


writer.println("bye!!!");




} else ...{


dispatch(line);


}


}






private void dispatch(String line) throws Exception ...{


String[] parts = line.split("/W");


ServiceReference[] channels = context.getServiceReferences(


IChannel.class.getName(), "(" + CHANNEL_NAME + "=" + parts[0]


+ ")");




if (channels != null) ...{


IChannel channel = (IChannel) context.getService(channels[0]);


channel.send(user, line.substring(parts[0].length()));


context.ungetService(channels[0]);




} else ...{


send("error", "not such user" + user);


}


}


}

当有一个客户请求的时候,它就新建以个Handler.要发送信息的功能在Handler中实现.
就这么简单了,还有几个问题要注意:
这个Component插件的META-INF/MANIFEST.MF:


Manifest-Version: 1.0


Bundle-ManifestVersion: 2


Bundle-Name: Telnet Plug-in


Bundle-SymbolicName: org.dengues.zos.chat.telnet


Service-Component: OSGI-INF/telnet_component.xml


Bundle-Version: 1.0.0


Bundle-Activator: org.dengues.zos.chat.telnet.TelnetActivator


Import-Package: org.dengues.zos.chat.channel,


org.osgi.framework;version="1.3.0",


org.osgi.service.component;version="1.0.0",


org.osgi.service.log;version="1.3.0"


Eclipse-LazyStart: true

还有在运行的时候要选中两个插件:org.eclipse.equinox.ds(如果没有这个需要到Eclipse官网下),org.eclipse.equinox.log.这样运行后的结果:




osgi> ss




Framework is launched.




id State Bundle


0 ACTIVE org.eclipse.osgi_3.3.0.v20070530


1 ACTIVE javax.servlet_2.4.0.v200706111738


8 ACTIVE org.eclipse.osgi.services_3.1.200.v20070605


17 ACTIVE org.dengues.zos.chat_1.0.0


18 ACTIVE org.dengues.zos.chat.telnet_1.0.0


19 ACTIVE org.eclipse.equinox.ds_1.0.0.v20070226


20 ACTIVE org.eclipse.equinox.log_1.0.100.v20070226




osgi> log


>Info [20] Log created; Log Size=100; Log Threshold=4 initial@reference:file:plugins/org.eclipse.equinox.log_1.0.100.v20070226.jar/


>Info [20] ServiceEvent REGISTERED {service.id=22}


>Info [20] ServiceEvent REGISTERED {service.id=23}


>Info [20] ServiceEvent REGISTERED {service.id=24}


>Info [20] BundleEvent STARTED initial@reference:file:plugins/org.eclipse.equinox.log_1.0.100.v20070226.jar/


>Info [0] FrameworkEvent STARTLEVEL CHANGED System Bundle


>Info [18] Component active!!!!! initial@reference:file:../workspaces/org.dengues.zos.chat.telnet/




osgi>

可以看到Info[18],说明这个Component已经运行.
然后再打开两个Telnet, 使用 open localhost 55555.就可以聊天了!
注明:整个Dengues的代码文件太多,无法上传,如果需要源代码。请到用一下方式联系:
QQ群:24885404;Google群:http://groups.google.com/group/dengues.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐