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

最近使用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.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值