📄 serverconnection.java
字号:
/* * Copyright (c) 2003 - 2007, Silvio Meier and Tobias Reinhard * * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * o Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * o Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * o The names of its contributors may not be used to endorse * or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */package net.sf.cscc;import java.net.Socket;/** * Provides the functionality for the connection between a client and a server. * The connection to the server is specified by giving a port number and a * server name (Internet DNS name or IP address). * * @author Silvio Meier (SM) * @copyright Silvio Meier, Tobias Reinhard, 2003 * @history 2003-05-09 SM First Version * 2003-05-14 SM working on additional methods and events, * correction of some comments. * 2003-05-17 SM Comments corrected * 2003-05-20 TR Comments corrected * 2003-06-04 SM Outgoing queue removed is associated * to the ObjectSender. * 2003-06-04 SM Now using dispatcher thread of type * {@link net.sf.cscc.DataDispatcher} for dispatching. * incoming messages. * 2003-06-11 SM Some null pointer exception, * the connection breaks. Problem is now fixed * 2003-06-12 SM Now the connection flag is only set to true, * if the connection could be really established * 2003-06-12 SM New method inserted. * 2003-06-24 SM Exception handling extended, mishandling of exception * corrected. * 2003-06-26 SM If opening a connection does not work, all * resources are now freed. * 2004-12-13 SM Some cleaning of unused things. * 2006-11-28 SM Comments revised. * @version $Date: 2007/07/01 17:04:05 $, $Author: reode_orm $, $Revision: 1.1 $ * @responsibilities Controls the connection between a client and a server. * @invariant - * @obligation - */class ServerConnection implements CommunicationController { /** * Thread which is responsible for sending objects. */ private ObjectSender sender = null; /** * Thread which is responsible for receiving objects. */ private ObjectReceiver receiver = null; /** * TCP/IP Socket for the connection. */ private Socket socket = null; /** * Represents the event queue for the incoming messages (the messages * arriving from the client). */ private Queue inComingMessages; /** * Status of the connection to the server. This flag is set true, if the connection * is open. */ private boolean connected = false; /** * Represents the data observable object which posts all the data events * to interested observers. */ private DataEventObservable dataObservable; /** * Represents the communication observable object which posts all the communication events * to interested observers. */ private CommunicationEventObservable communicationObservable; /** * Dispatcher which notifies and sends data events to the interested * observers. */ DataDispatcher dataDispatcher; /** * The port number used to connect to the server. */ private int portNumber; /** * The constructor initializes the server connection. * It does not automatically * connect to the server. This has to be done by calling the method * {@link #open(String serverName)}. * * @pre portNumber >= 0 && o != null && co != null * @post true * @param portNumber Number of the port used for the connection to the * server. * @param o Observable which notifies interested observers about new * data events in the incoming event queue. * @param co Observable wich notifies interested observers about new * communication events. */ public ServerConnection(int portNumber, DataEventObservable o, CommunicationEventObservable co) { dataObservable = o; communicationObservable = co; inComingMessages = new Queue(); this.portNumber = portNumber; } /** * Opens a new connection using the TCP/IP connection to the specified port number specified by calling * the constructor * {@link #ServerConnection(int portNumber, DataEventObservable o, CommunicationEventObservable co)}. * The server is specified by the parameter serverName. * * @pre serverName != null * @post connected == true * @param serverName Name of the server to connect. This is either * specified as Internet DNS name or as IP address. */ public boolean open(String serverName) { try{ // new message dispatcher for incoming messages dataDispatcher = new DataDispatcher(dataObservable, inComingMessages); //New socket connection to the server socket = new Socket(serverName, portNumber); sender = new ObjectSender(socket, this); receiver = new ObjectReceiver(socket, this); communicationObservable.notifyCommunicationEventObservers( new CommunicationEvent(CommunicationEvent.CONNECTION_ESTABLISHED)); connected = true; } catch (Exception e) { try { if (sender != null) sender.close(); } catch (Exception ex) { } try { if (receiver != null) receiver.close(); } catch (Exception ex) { } try { if (socket != null) socket.close(); } catch (Exception ex) { } try { dataDispatcher.stopDispatching(); } catch (Exception ex) { } sender = null; receiver = null; socket = null; dataDispatcher = null; } return connected; } /** * Closes the connection to the server by closing the receiving * and sending threads of the connection. * * @pre - * @post connected == false */ public void close() { if (connected) { connected = false; try { communicationObservable.notifyCommunicationEventObservers( new CommunicationEvent(CommunicationEvent.CONNECTION_CLOSED)); if (sender != null) sender.close(); if (receiver != null) receiver.close(); if (socket != null) socket.close(); if (dataDispatcher != null) dataDispatcher.stopDispatching(); sender = null; receiver = null; socket = null; dataDispatcher = null; } catch (Exception e) { throw new CsccException(e.getMessage()); } } } /** * This method sends a DataEvent object from the client to the server. * This happens asynchronous, i.e. the method returns immediately. * The sending is afterwards done in the background. * @pre de != null * @post true * @param de DataEvent object which should be sent to the server. */ public void enqueueDataEvent(DataEvent de) { if (sender != null) { sender.enqueueDataEvent(de); } } /** * This method returns the oldest DataEvent object received * from the server. The DataEvent object is left in the event queue * that means, calling this method a second time resutls in the same * returned event, if, and only if the event was not removed in * the meantime. * * @pre true * @post true * @return Returns the oldest DataEvent object in the event queue without * removing it from the queue. */ public DataEvent getDataEvent() { return inComingMessages.getDataEvent(); } /** * This method returns the oldest DataEvent object in the incoming event * queue. This method removes the element after returning it from * the event queue. * * @pre true * @post true * @return Returns the oldest DataEvent object and removes it from * the event queue. */ public DataEvent dequeueDataEvent() { return inComingMessages.dequeueDataEvent(); } /** * This method is used to remove manually the oldest event in the * incoming event queue. * * @pre true * @post true */ public void removeDataEvent() { inComingMessages.removeDataEvent(); } /** * This method returns true, if any DataEvent object is in the event * queue. * * @pre true * @post true * @return Returns true, if there are events in the event queue. */ public boolean hasDataEvents() { return inComingMessages.hasDataEvents(); } /** * This method is the implementation of the {@link net.sf.cscc.CommunicationController} * interface. It handles the breaking of a connection. * * @pre eventSender != null * @post true * @param eventSender sender or receiver that broke the connection */ public void communicationBroken(Object eventSender) { try { if (eventSender == sender) { receiver.close(); socket.close(); } if (eventSender == receiver) { sender.close(); socket.close(); } } catch (Exception ex) { //ex.printStackTrace(); } communicationObservable.notifyCommunicationEventObservers( new CommunicationEvent(CommunicationEvent.CONNECTION_BROKEN)); if (dataDispatcher != null) { dataDispatcher.stopDispatching(); } dataDispatcher = null; receiver = null; sender = null; socket = null; } /** * Sets the port number for a connection. The newly set port number will * be used as soon a new connection to the server is established. * * @pre portNumber >= 0 * @post this.portNubmer == portNumber * @param portNumber Determines the TCP/IP port number which is used * to connect the next time to the server. */ public void setPortNumber(int portNumber) { this.portNumber = portNumber; } /** * This method returns the currently set port number. This port number * is used to connect to the server. * * @pre true * @post return == this.portNumber * @return Returns the currently set TCP/IP port number which is used to * connect to the server */ public int getPortNumber() { return this.portNumber; } /** * This method is used internally to enqueue new events to the * incoming data event queue. * * @pre de != null * @post return == this.portNumber * @param de DataEvent which should be enqueued into the incoming data * events queue. */ public void enqueueIncomingDataEvent(DataEvent de) { // should be done without disturbing through another // thread otherwise the order of the events is not garanteed! synchronized (inComingMessages) { inComingMessages.enqueueDataEvent(de); dataDispatcher.notifyDispatch(); } } /** * Returns true, if the connection to the server is open. * * @pre true * @post true */ public boolean isOpen() { return connected; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -