📄 serversocketthread.java
字号:
// ----------------------------------------------------------------------------// Copyright 2006-2008, Martin D. Flynn// All rights reserved// ----------------------------------------------------------------------------//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// // http://www.apache.org/licenses/LICENSE-2.0// // Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.//// ----------------------------------------------------------------------------// Description:// Template for general server socket support// ----------------------------------------------------------------------------// Change History:// 2006/03/26 Martin D. Flynn// -Initial release// 2006/06/30 Martin D. Flynn// -Repackaged// 2007/05/01 David Cowan// -Added support for gracefully shutting down the server// 2007/07/13 Martin D. Flynn// -End Of Stream errors on UDP connections simply returns the bytes we're // just read (previously it threw an exception, and ignored the received data).// ----------------------------------------------------------------------------package org.opengts.util;import java.io.*;import java.util.*;import java.net.*;import java.awt.event.*;import javax.net.ssl.*;import javax.net.*;public class ServerSocketThread extends Thread{ // ------------------------------------------------------------------------ // References: // http://tvilda.stilius.net/java/java_ssl.php // http://www.jguru.com/faq/view.jsp?EID=993651 // ------------------------------------------------------------------------ // SSL: // keytool -genkey -keystore <mySrvKeystore> -keyalg RSA // Required Properties: // -Djavax.net.ssl.keyStore=<mySrvKeystore> // -Djavax.net.ssl.keyStorePassword=<123456> // For debug, also add: // -Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol // -Djavax.net.debug=ssl // ------------------------------------------------------------------------ public static final int PACKET_LEN_ASCII_LINE_TERMINATOR = -1; public static final int PACKET_LEN_END_OF_STREAM = -2; // ------------------------------------------------------------------------ private int listenPort = 0; private DatagramSocket datagramSocket = null; private ServerSocket serverSocket = null; private java.util.List<ServerSessionThread> clientThreadPool = null; private ClientPacketHandler clientPacketHandler = null; private Class clientPacketHandlerClass = null; private long sessionTimeoutMS = -1L; private long idleTimeoutMS = -1L; private long packetTimeoutMS = -1L; private int lingerTimeoutSec = 4; // SO_LINGER timeout is in *Seconds* private int maxReadLength = -1; private int minReadLength = -1; private boolean terminateOnTimeout = true; private boolean isTextPackets = true; private int lineTerminatorChar[] = new int[] { '\n' }; private int backspaceChar[] = new int[] { '\b' }; private int ignoreChar[] = new int[] { '\r' }; private byte prompt[] = null; private int promptIndex = -1; private boolean autoPrompt = false; private java.util.List<ActionListener> actionListeners = null; // ------------------------------------------------------------------------ private ServerSocketThread() { this.clientThreadPool = new Vector<ServerSessionThread>(); this.actionListeners = new Vector<ActionListener>(); } public ServerSocketThread(DatagramSocket ds) { this(); this.datagramSocket = ds; this.listenPort = (ds != null)? ds.getLocalPort() : -1; } public ServerSocketThread(ServerSocket ss) { this(); this.serverSocket = ss; this.listenPort = (ss != null)? ss.getLocalPort() : -1; } public ServerSocketThread(int port) throws IOException { this(new ServerSocket(port)); this.listenPort = port; } public ServerSocketThread(int port, boolean useSSL) throws IOException { this(useSSL? SSLServerSocketFactory.getDefault().createServerSocket(port) : ServerSocketFactory .getDefault().createServerSocket(port) ); this.listenPort = port; } // ------------------------------------------------------------------------ public void run() { while (true) { ClientSocket clientSocket = null; /* wait for client session */ try { if (this.serverSocket != null) { clientSocket = new ClientSocket(this.serverSocket.accept()); } else if (this.datagramSocket != null) { byte b[] = new byte[ServerSocketThread.this.getMaximumPacketLength()]; ServerSocketThread.this.getMaximumPacketLength(); DatagramPacket dp = new DatagramPacket(b, b.length); this.datagramSocket.receive(dp); clientSocket = new ClientSocket(dp); } else { Print.logStackTrace("ServerSocketThread has not been properly initialized"); } } catch (SocketException se) { // shutdown support if (this.serverSocket != null) { int port = this.serverSocket.getLocalPort(); if (port <= 0) { port = this.listenPort; } String portStr = (port <= 0)? "?" : String.valueOf(port); Print.logInfo("Shutdown TCP server on port " + portStr); } else if (this.datagramSocket != null) { int port = this.datagramSocket.getLocalPort(); if (port <= 0) { port = this.listenPort; } String portStr = (port <= 0)? "?" : String.valueOf(port); Print.logInfo("Shutdown UDP server on port " + portStr); } else { Print.logInfo("Shutdown must have been called"); } break; } catch (IOException ioe) { Print.logError("Connection - " + ioe); continue; // go back and wait again } /* ip address */ String ipAddr; try { InetAddress inetAddr = clientSocket.getInetAddress(); ipAddr = (inetAddr != null)? inetAddr.getHostAddress() : "?"; } catch (Throwable t) { ipAddr = "?"; } /* find an available client thread */ boolean foundThread = false; for (Iterator i = this.clientThreadPool.iterator(); i.hasNext() && !foundThread;) { ServerSessionThread sst = (ServerSessionThread)i.next(); foundThread = sst.setClientIfAvailable(clientSocket); } if (!foundThread) { // add new thread to pool //Print.logInfo("New thread for ip ["+ipAddr+"] ..."); ServerSessionThread sst = new ServerSessionThread(clientSocket); this.clientThreadPool.add(sst); } else { //Print.logDebug("Reuse existing thread for ip ["+ipAddr+"] ..."); } } } public void shutdown() { try { /* shutdown TCP listener */ if (this.serverSocket != null) { this.serverSocket.close(); } /* shutdown UDP listener */ if (this.datagramSocket != null) { this.datagramSocket.close(); } /* loop through, and close all server threads */ Iterator it = this.clientThreadPool.iterator(); while (it.hasNext()) { ServerSessionThread sst = (ServerSessionThread)it.next(); if (sst != null) { sst.close(); } } } catch (Exception e) { Print.logError("Error shutting down ServerSocketThread " + e); } } // ------------------------------------------------------------------------ public boolean hasListeners() { return (this.actionListeners.size() > 0); } public void addActionListener(ActionListener al) { // used for simple one way messaging if (!this.actionListeners.contains(al)) { this.actionListeners.add(al); } } public void removeActionListener(ActionListener al) { this.actionListeners.remove(al); } protected boolean invokeListeners(byte msgBytes[]) throws Exception { if (msgBytes != null) { String msg = StringTools.toStringValue(msgBytes); for (Iterator i = this.actionListeners.iterator(); i.hasNext();) { Object alObj = i.next(); if (alObj instanceof ActionListener) { ActionListener al = (ActionListener)i.next(); ActionEvent ae = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, msg); al.actionPerformed(ae); } } return true; } else { return false; } } // ------------------------------------------------------------------------ public void setClientPacketHandler(ClientPacketHandler cph) { this.clientPacketHandler = cph; } public void setClientPacketHandlerClass(Class cphc) { if ((cphc == null) || ClientPacketHandler.class.isAssignableFrom(cphc)) { this.clientPacketHandlerClass = cphc; this.clientPacketHandler = null; } else { throw new ClassCastException("Invalid ClientPacketHandler class"); } } public ClientPacketHandler getClientPacketHandler() { if (this.clientPacketHandler != null) { // single instance return this.clientPacketHandler; } else if (this.clientPacketHandlerClass != null) { // new instance try { return (ClientPacketHandler)this.clientPacketHandlerClass.newInstance(); } catch (Throwable t) { Print.logException("ClientPacketHandler", t); return null; } } else { // not defined return null; } } // ------------------------------------------------------------------------ public void setSessionTimeout(long timeoutMS) { this.sessionTimeoutMS = timeoutMS; } public long getSessionTimeout() { return this.sessionTimeoutMS; } // ------------------------------------------------------------------------ public void setIdleTimeout(long timeoutMS) { this.idleTimeoutMS = timeoutMS; } public long getIdleTimeout() { // the timeout for waiting for something to appear on the socket return this.idleTimeoutMS; } public void setPacketTimeout(long timeoutMS) { // once a byte is finally read, the timeout for waiting until the // entire packet is finished this.packetTimeoutMS = timeoutMS; } public long getPacketTimeout() { return this.packetTimeoutMS; } public void setTerminateOnTimeout(boolean timeoutQuit) { this.terminateOnTimeout = timeoutQuit; } public boolean getTerminateOnTimeout() { return this.terminateOnTimeout; } // ------------------------------------------------------------------------ public void setLingerTimeoutSec(int timeoutSec) { this.lingerTimeoutSec = timeoutSec; } public int getLingerTimeoutSec() { return this.lingerTimeoutSec; } // ------------------------------------------------------------------------ public void setTextPackets(boolean isText) { this.isTextPackets = isText; if (!this.isTextPackets()) { this.setBackspaceChar(null); //this.setLineTerminatorChar(null); this.setIgnoreChar(null); } } public boolean isTextPackets() { return this.isTextPackets; } // ------------------------------------------------------------------------ public void setMaximumPacketLength(int len) { this.maxReadLength = len; } public int getMaximumPacketLength() { if (this.maxReadLength > 0) { return this.maxReadLength; } else if (this.isTextPackets()) { return 2048; // default for text packets } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -