📄 server.java
字号:
/** * Communicates with a single client. On connection spawns a new thread. * * @author Martin Vysny */ protected class Listener extends Thread { private volatile L2CAPConnectionNotifier notifier = null; /** * Client connection. */ private volatile L2CAPConnection connection = null; /** * Valid when {@link #state} is {@link #STATE_CONNECTED} or * {@link #STATE_TERMINATING}. */ private byte id = -1; /** * Current state of the thread. */ private volatile int state = STATE_NEW; /** * Thread is newly created. */ private final static int STATE_NEW = 0; /** * Thread is waiting for a client to connect. */ private final static int STATE_LISTENING = 1; /** * Thread is connected to a client. */ private final static int STATE_CONNECTED = 2; /** * Thread is terminating, connection is closed. */ private final static int STATE_TERMINATING = 3; /** * Received data is placed here. */ private final byte[] receiverBuffer = new byte[receiveMTU]; /** * Client's device name, valid after a connection is established. */ public String deviceName; /* * (non-Javadoc) * * @see java.lang.Thread#run() */ public void run() { Logger.debug("Server.Listener?.run(): starting", null); //$NON-NLS-1$ try { try { if (!initializeConnection()) return; } finally { if (state == STATE_TERMINATING) return; // spawn new connection if available if (connectedClients.size() < Peer.MAX_CLIENTS) { waitingForConnectionListener = new Listener(); waitingForConnectionListener.start(); } } try { listenLoop(); } finally { // finally, close the connection close(); } } catch (Exception ex) { Logger.error("Server.Listener" + id + ".run()", ex); //$NON-NLS-1$ //$NON-NLS-2$ } finally { Logger.debug("Server.Listener" + id + ".run(): terminating", //$NON-NLS-1$//$NON-NLS-2$ null); } } /** * Waits for a connection and initializes it. * * @return <code>true</code> if the connection was initialized * succesfully, <code>false</code> otherwise. */ private boolean initializeConnection() { int hint = IServerListener.ERROR_HINT_WAITING_FOR_CONNECTION; // wait for connection try { notifier = (L2CAPConnectionNotifier) Connector.open( listenerURL, Connector.READ_WRITE, true); state = STATE_LISTENING; Logger.debug( "Server.Listener?.initializeConnection(): listening", //$NON-NLS-1$ null); connection = notifier.acceptAndOpen(); // initialize the connection synchronized (connectedClients) { hint = IServerListener.ERROR_HINT_OPENING_CONNECTION; if (state == STATE_TERMINATING) return false; Logger .debug( "Server.Listener?.initializeConnection(): incoming connection", //$NON-NLS-1$ null); // get init packet. final byte id = getFreeClientId(); final ByteArrayOutputStream outByte = new ByteArrayOutputStream(); final DataOutputStream out = new DataOutputStream(outByte); out.writeByte(id); out.close(); connection.send(outByte.toByteArray()); final int bytesReceived = connection .receive(receiverBuffer); final DataInputStream stream = new DataInputStream( new ByteArrayInputStream(receiverBuffer, 0, bytesReceived)); deviceName = stream.readUTF(); // initialize schedulers and stuff this.id = id; waitingForConnectionListener = null; state = STATE_CONNECTED; connectedClients.put(Peer.getID(id), this); scheduler.addRoute(Peer.getID(id), connection); // close the notifier notifier.close(); notifier = null; // invoke the listener try { ((IServerListener) listener).clientConnected(id, deviceName); } catch (Exception ex) { invokeErrorOccured(id, hint, "clientConnected()", ex); //$NON-NLS-1$ close(); return false; } } return true; } catch (Exception ex) { Logger.log(state == STATE_TERMINATING ? Logger.LEVEL_INFO : Logger.LEVEL_ERROR, "Server.Listener" + id //$NON-NLS-1$ + ".initializeConnection()", ex); //$NON-NLS-1$ if (state != STATE_TERMINATING) invokeErrorOccured(id, hint, null, ex); close(); } return false; } /** * Listen loop. Listens for data and invokes events when data is * received. */ private void listenLoop() { Logger.debug("Server.Listener" + id //$NON-NLS-1$ + ".listenLoop(): listening for data", null); //$NON-NLS-1$ // listen for data try { while (true) { final int bytesReceived = connection .receive(receiverBuffer); final DataInputStream stream = new DataInputStream( new ByteArrayInputStream(receiverBuffer, 0, bytesReceived)); // invoke the listener try { ((IServerListener) listener).messageArrived(id, deviceName, receiverBuffer, bytesReceived, stream); } catch (Exception ex) { invokeErrorOccured(id, IErrorListener.ERROR_HINT_COMMUNICATING, "messageArrived()", ex); //$NON-NLS-1$ } } } catch (Exception ex) { Logger.log(state == STATE_TERMINATING ? Logger.LEVEL_INFO : Logger.LEVEL_ERROR, "Server.Listener" + id //$NON-NLS-1$ + ".listenLoop()", ex); //$NON-NLS-1$ if (state != STATE_TERMINATING) invokeErrorOccured(id, IServerListener.ERROR_HINT_COMMUNICATING, null, ex); } } /** * Close the connection and free all resources. */ public void close() { Logger.info( "Server.Listener" + id + ".close(): closing connection", //$NON-NLS-1$//$NON-NLS-2$ null); final boolean wasConnected = (state == STATE_CONNECTED); state = STATE_TERMINATING; if (id != -1) synchronized (connectedClients) { connectedClients.remove(Peer.getID(id)); final PacketScheduler scheduler = Server.this.scheduler; if (scheduler != null) { scheduler.removeRoute(Peer.getID(id)); } } try { final L2CAPConnectionNotifier notifier = this.notifier; if (notifier != null) { notifier.close(); this.notifier = null; } final L2CAPConnection connection = this.connection; if (connection != null) { connection.close(); this.connection = null; } } catch (IOException e) { Logger.info("Server.Listener" + id + ".close()", e); //$NON-NLS-1$ //$NON-NLS-2$ invokeErrorOccured(id, IServerListener.ERROR_HINT_CLOSING_CONNECTION, null, e); } if (wasConnected) { // invoke the listener try { ((IServerListener) listener).clientDisconnected(id, deviceName); } catch (Exception ex) { invokeErrorOccured(id, IServerListener.ERROR_HINT_CLOSING_CONNECTION, "clientDisconnected()", ex); //$NON-NLS-1$ } } } } /** * Disconnects given client from the server. If no such client is connected * then nothing happens. * * @param clientID * the client's ID to disconnect. */ public void disconnectClient(final byte clientID) { synchronized (connectedClients) { final Listener l = (Listener) connectedClients.get(Peer .getID(clientID)); if (l == null) return; l.close(); } } /** * Internal method, not intended to be called by users. */ public void errorOccured(byte clientID, int errorHint, final boolean listenerError, Exception ex) { // errors from scheduler. Disconnect this client. invokeErrorOccured(clientID, errorHint, null, ex); disconnectClient(clientID); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -