package ctitest.applet;
import java.applet.Applet;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.List;
import netscape.javascript.JSObject;
/**
* Socket服务类。 消息分类: a)接收到的消息: 若首字节为“1”,表示“页面跳转地址”消息,从第二字节开始为“消息”;
* 若首字节为“2”,表示“页面提示”消息,从第二字节开始为“消息”; 若首字节为“3”,表示“请求屏幕截图”消息。 b)发送出的消息:
* 若首字节为“1”,表示“服务器连接不通过”消息,从第二字节开始为“消息”; 若首字节为“2”,表示发送到客户端“页面提示”消息,从第二字节开始为“消息”;
* 若首字节为“3”,表示发送到客户端“屏幕截图”消息,从第二字节开始为“消息”。 c)所有异常消息,首字节均为“9”
*
* @author haiw
*/
public class CTIServer extends Applet {
private static final long serialVersionUID = -5187436480346154595L;
private static ServerSocket serverSocket;
private static CTIServer server;
private static int port;
private static Client client; // 客户连接
private static JSObject jso;
private static String jsMsgHandler; // 消息处理js函数名
private static String screenImgPath; // 屏幕截图存放路径
public void init() {
super.init();
port = Integer.parseInt(getParameter("port"));
jso = JSObject.getWindow(this);
jsMsgHandler = getParameter("jsMsgHandler");
screenImgPath = getParameter("screenImgPath");
new StartupServerThread(1000L).start();
}
public void destroy() {
super.destroy();
terminate();
}
/**
* 获取服务,没有则创建
*/
private static CTIServer getInstance() throws Exception {
if (server == null) {
server = new CTIServer();
System.out.println("begin server.startup");
server.startupPrivileged();
}
return server;
}
/**
* 启动服务,接收客户端
*/
protected void startup() {
try {
serverSocket = new ServerSocket(port);
System.out.println("finish serverSocket:" + serverSocket);
new ServerThread().start();
} catch (Exception ex) {
terminate();
ex.printStackTrace();
if ((ex instanceof BindException))
msgHandler(9, ex.getMessage());
}
}
private void startupPrivileged() {
Exception ex = (Exception) AccessController
.doPrivileged(new CTIServerStartupPrivileged(this));
if (ex != null) {
ex.printStackTrace();
}
}
/**
* 销毁服务
*/
private void terminate() {
System.out.println("terminate");
try {
serverSocket.close();
} catch (Exception ex) {
}
serverSocket = null;
client = null;
server = null;
}
/**
* 向客户端发送“页面提示”消息
*/
protected void sendMsg(String msg) {
try {
if (client != null && client.socket != null) {
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(client.socket.getOutputStream(),
"UTF-8"));
writer.write("2" + msg + "\n");
writer.flush();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void sendMsgPrivileged(String msg) {
Exception ex = (Exception) AccessController
.doPrivileged(new CTIServerSendMsgPrivileged(msg, this));
if (ex != null) {
ex.printStackTrace();
}
}
/**
* 调用javascript处理接收到的消息: 1表示“页面跳转地址”消息; 2表示“页面提示”消息;
*/
private void msgHandler(int type, String msg) {
try {
System.out.println(type);
jso.call(jsMsgHandler, new Object[] { type, msg });
} catch (Exception ex) {
ex.printStackTrace();
}
}
// 连接的客户端
private class Client {
private Socket socket;
private long timeout; // 停留时间(最后一次发送消息后停留时间)
private Client(Socket socket) {
this.socket = socket;
this.timeout = 0;
}
private void close() {
if (socket != null) {
try {
socket.close();
} catch (Exception ex) {
}
socket = null;
}
timeout = 0;
}
}
// 服务线程
private class ServerThread extends Thread {
public void run() {
try {
while (true) {
Socket socket = serverSocket.accept(); // 接收客户端连接
client = new Client(socket);
new MsgThread().start(); // 消息处理线程
// 连接后,超过60秒未发送消息,客户端自动断开
new TimeoutCheckerThread(60000L).start();
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
terminate();
}
}
}
// 通信线程
private class MsgThread extends Thread {
private Socket socket;
private BufferedReader reader;
private BufferedWriter writer;
private MsgThread() {
}
public void run() {
try {
this.socket = CTIServer.client.socket;
System.out.println("连接建立:" + this.socket);
this.reader = new BufferedReader(new InputStreamReader(
this.socket.getInputStream(), "UTF-8"));
this.writer = new BufferedWriter(new OutputStreamWriter(
this.socket.getOutputStream(), "UTF-8"));
while (!this.socket.isClosed()) {
List<Integer> chs = new ArrayList<Integer>();
int i = -1;
while ((i = this.reader.read()) != -1) {
if ((i == 13) || (i == 10) || (i == 0)) {
break;
}
chs.add(Integer.valueOf(i));
}
if ((i == -1) && (chs.size() == 0)) {
System.out.println("已到达流末尾,线程结束");
break;
}
if (chs.size() == 0) {
continue;
}
char[] ch = new char[chs.size()];
for (int j = 0; j < ch.length; j++) {
ch[j] = (char) ((Integer) chs.get(j)).intValue();
}
String msg = new String(ch);
System.out.println("接收到原始消息:" + msg);
CTIServer.client.timeout = 0L;
if (msg.startsWith("1")) {
CTIServer.this.msgHandler(1, msg.substring(1));
} else if (msg.startsWith("2")) {
CTIServer.this.msgHandler(2, msg.substring(1));
} else if (msg.startsWith("3")) {
try {
byte[] screenByte = ScreenCapture.getInstance()
.printScreen(
CTIServer.screenImgPath
+ "/SCREEN_IMG.jpeg");
String screenStr = BASE64.encode(screenByte);
screenStr = screenStr.replaceAll("\r",
"LSRLSRLSRLSR").replaceAll("\n",
"LSNLSNLSNLSN");
this.writer.write("3" + screenStr + "\n");
this.writer.flush();
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
System.out.println("格式不正确消息:" + msg);
}
}
} catch (Exception localException1) {
} finally {
System.out.println("连接断开:" + this.socket);
if (this.writer != null) {
try {
this.writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (this.reader != null) {
try {
this.reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (this.socket != null) {
try {
this.socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
CTIServer.client.close();
this.writer = null;
this.reader = null;
this.socket = null;
CTIServer.client = null;
}
}
}
// 每隔指定时间检查服务是否启动
private class StartupServerThread extends Thread {
private long delay;
private StartupServerThread(long delay) {
this.delay = delay;
}
public void run() {
try {