四、为什么要采用Java编写NT服务
比较VC等“原装”NT服务开发方式而言,Java开发模式可以更快捷,因为几乎所有得服务框架通过扩展Services类就可以达到,省下不少复杂的细节处理。Java语言提供了丰富的类库,可以为自己使用,可以提高效率,而且编写的程序结构清楚轻易理解,方便以后维护。
Java提供的异常处理模式,可以让我们写好结构良好,更加安全的代码。试想假如编写的服务进程由于采用VC编写却忘记对某块内存的释放,那么服务启动后一段时间由于内存泄漏造成服务性能下降,甚至系统崩溃;但是Java本身的语言特性可以使我们不用时刻提防内存治理,可以更加关注服务逻辑本身,是的实现起来更加有效率。
采用VC假如编写多线程服务进程,虽然可以实现,但是会相当麻烦。而服务进程多线程几乎是每一个性能良好的服务必备特征,Java语言本身可以提供这方面良好的支持,同时Java自身对网络的天然良好支持,使各种网络套接字编程轻易。
最后,假如不采用其他扩展库,我们很轻易将此服务逻辑实现在其他操作系统上。一个编写好的NT服务程序,可以在去掉对Ms的相关本地化扩展实现的类引用后,方便移植到其他例如Linux等平台上,尽可能向Java的“一次编写、到处可运行”的理想境界靠拢。
五、源码
/*所附的ZIP文件报含示例的全部工程文件,还有编译后的NT服务的可执行文件,您可以直接测试此服务exe文件的安装、服务启停*/
/*EchoSvc.java*/
import com.ms.service.* ;
public class EchoSvc extends Service
{
static Thread mainSvc=null ; //定义主线程
public EchoSvc (String[] args) //构造服务
{
CheckPoint(1000); //服务是系统的一部分,作为Log纪录,可以帮助用户理解系统故障
setRunning(ACCEPT_SHUTDOWN ACCEPT_PAUSE_CONTINUE ACCEPT_STOP);
mainSvc = new Thread((Runnable) new MainSvcThread());
mainSvc.start();
System.out.println( "The Echo Service Was Started SUCcessfully!");
}
}
/*-------------- EchoSvc.java源码结束-------------------*/
/*MainSvcThread.java*/
import java.io.*;
import java.net.*;
public class MainSvcThread implements Runnable //实现线程控制多线程接口
{ /将启动一组线程来监听多个服务请求
public static boolean STOP = false; //由系统来控制的内部变量,决定着服务进程(线程)的启动、暂停等
public static boolean PAUSE = false;
public int ListenThreadCount=0; //本服务支持的当前线程数量
int maxSocket=10; //最大支持的同时连结数
int SvcPort=2002; //服务监听的端口
public void run()
{
try
{
while (!STOP)
{
while (!PAUSE && !STOP)
{
{//创建监听服务器
Socket server;
ServerSocket li=new ServerSocket(SvcPort); //创建服务器端套接字
ThreadGroup g=new ThreadGroup("EchoThreads"); //创建一组线程
System.out.println("Echo service starting..."); //记录在Log中
while(ListenThreadCount<maxSocket)
{
server=li.accept(); //监听
EchoThread p=new EchoThread(server,this); //创建服务单线程
Thread t=new Thread(g,(Runnable)p) ; //创建新线程
t.start(); //启动服务线程
ListenThreadCount++; //当前线程的数量
}
}
try
{
Thread.sleep(5000);//暂停5秒
}
catch (InterruptedException e)
{ }
}
try
{
Thread.sleep(1000);
}
catch (InterruptedException ie)
{ }
}
}
catch (IOException ioe)
{}
} //Run结束
}
/*-------------- MainSvcThread.java源码结束-------------------*/
/*EchoThread.java*/
import java.io.*;
import java.net.*;
/*实现每一个客户连接到此NT服务时的服务器端的线程单元逻辑*/
public class EchoThread implements Runnable //实现线程接口
{
Socket so=null;//套接字
MainSvcThread p; //一个指向父线程的指针,EchoThread的线程是服务线程的创建的子线程
public void run()
{
String line;
DataInputStream in; //套接字上的输入流
PrintWriter out; //套接字上的输出流,带缓冲
boolean exitflag=false;
try
{
in=new DataInputStream(so.getInputStream()) ;//获取套接字的输入流
out=new PrintWriter(new DataOutputStream(so.getOutputStream())) ;
out.println("You have connected to EchoSvc!"); //发送问候
out.flush(); //必须刷新缓冲区内的内容
while((line=in.readLine())!=null && ! exitflag)
{
line=line.trim();
if (line.equalsIgnoreCase("quit") )
{//假如是退出命令,则关闭当前套接字上的输入输出流
in.close();
out.flush();
out.close();
p.ListenThreadCount --; //主线程的服务线程单元数量控制
return; //退出当前的服务逻辑线程单元
}
else
{
out.println("ECHO:" + line );
out.flush();
}
}
in.close();
out.close();
p.ListenThreadCount --;
}
catch(IOException ioe)
{}
}
EchoThread(Socket s,MainSvcThread parent)
{
so=s;
p= parent;
}
}
/*-------------- EchoThread.java源码结束-------------------*/