📄 netconnection.java
字号:
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To queue a message you want to send.
*
* This method works with every connection type but has different behaviours. If your
* connection type is asynchronous this method will just leave the message on a queue
* and the message will be sent automatically later. If the connection type is synchronous
* you'll have to call the sendAllMessages() method to signal that queued messages can now
* be sent.<br>
*
* The connection type depends on the implementation of this abstract NetConnection class
* Take a look at the provided implementation in wotlas.libs.net.connection .
*
* @param message message you want to send.
*/
public void queueMessage( NetMessage message ) {
if( myNetsender!=null )
myNetsender.queueMessage( message );
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Waits for a message to arrive. Useful in some cases when the NetReceiver
* is synchronous. This method does nothing if the NetReceiver is asynchronous.
*
* @exception IOException if an IO error occur.
*/
public void waitForMessage() throws IOException{
myNetreceiver.waitForMessage();
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To close this connection. Erases all the allocated resources. This method will return
* immediately but the remaining queued messages will still be sent. This method performs
* some clean-up on the NetConnection object and does nothing when called twice.
*/
synchronized public void close() {
if( myNetsender==null || myNetreceiver==null )
return;
// We send a EndOfConnection message to the other side
if( myNetsender!=null )
myNetsender.queueMessage( new EndOfConnectionMessage() );
// no more message handling
myNetreceiver.stopThread();
// we wait for the remaining messages to be sent
myNetsender.sendAllMessages();
// massive destruction
myNetsender.stopThread();
myNetsender.closeSocket(); // only lets the NetReceiver finish its work
// before closing
synchronized( myNetsender ) {
myNetsender.notify(); // we don't forget to wake up the thread !
} // (the NetSender is locked when there are no msgs )
if( pingLock!=null )
synchronized( pingLock ){
pingThread.stopThread();
}
for( int i=0; i<listeners.length; i++ )
listeners[i].connectionClosed( this );
myNetsender = null;
myNetreceiver = null;
listeners = null;
}
/*------------------------------------------------------------------------------------*/
/** To set a ping listener for this network connection. Ping messages will be added to
* this network connection and if the remote peer supports it, Ping info will be sent
* regularly to this listener.
* @param pListener the object that will receive ping information.
*/
public void setPingListener( NetPingListener pListener ) {
if(pListener==null)
return;
if( pingLock!=null )
synchronized( pingLock ) {
if( pingThread==null ) return; // No longer living net connnection
// just swap the listener
pingThread.pListener = pListener;
return;
}
// Ping Thread Creation
pingLock = new Object();
pingThread = new PingThread(pListener);
pingThread.start();
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To remove the current ping listener (if any) for this network connection.
*/
public void removePingListener() {
if( pingLock!=null )
synchronized( pingLock ) {
if( pingThread==null ) return; // No longer living net connnection
pingThread.pListener = null;
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Called by the NetReceiver when it receives a PingMessage (if not in SendBack mode).
* @param sequenceID ping message's sequence ID.
*/
protected void receivedPingMessage( int sequenceID ) {
if( pingLock==null ) return;
synchronized( pingLock ) {
if( pingThread==null || pingThread.sequenceID!=sequenceID)
return;
pingThread.lastPingValue = (int)(System.currentTimeMillis()-pingThread.lastPingT0);
pingThread.pingReceivedBack = true;
if(pingThread.pListener!=null)
pingThread.pListener.pingComputed( pingThread.lastPingValue );
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To set that this network connection must answer or not to ping messages.
* This option is not compatible with the setPingListener() method.
* You must choose between send back ping messages and compute the ping info.
* @param sendBack set to true if you want to send back ping messages.
*/
public synchronized void sendBackPingMessages( boolean sendBack ) {
if( pingLock!=null && sendBack ) {
Debug.signal( Debug.ERROR, this, "Conflict detected: ping thread exists ! Can't send back ping messages");
}
if( myNetreceiver!=null )
myNetreceiver.sendBackPingMessages( sendBack );
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** A Thread that send PingMessages and manages the ping info.
* It is created when a NetPingListener is first set and lives as long as the network
* connection does.
*/
private class PingThread extends Thread {
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
protected byte sequenceID; // current ping sequence ID
protected boolean pingReceivedBack; // has the last ping been received ?
protected int lastPingValue; // last ping value
protected long lastPingT0; // last ping sent t0
protected NetPingListener pListener; // our ping listener
protected boolean shouldStopPingThread;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Constructor with ping listener.
*/
public PingThread( NetPingListener pListener ) {
sequenceID = 0;
pingReceivedBack = false;
shouldStopPingThread = false;
this.pListener = pListener;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Our Ping Loop
*/
public void run(){
while( !shouldStopPingThread ) {
// 1 - We send a PingMessage to the other side
queueMessage( new PingMessage( sequenceID ) );
lastPingT0 = System.currentTimeMillis();
// 2 - We wait 2 seconds between two Ping.
synchronized( this ) {
try{
this.wait( 2000 );
}catch( Exception e ) {}
if(shouldStopPingThread)
break;
}
// 3 - Have we received the answer ?
synchronized( pingLock ) {
if(!pingReceivedBack) {
// we wait two more seconds
try{
this.wait( 2000 );
}catch( Exception e ) {
}
// if there is still no answer we declare the message lost
if( !pingReceivedBack ) {
lastPingValue = NetPingListener.PING_FAILED;
if(pListener!=null)
pListener.pingComputed( lastPingValue );
}
}
sequenceID = (byte) ( (sequenceID+1)%120 );
pingReceivedBack = false;
}
}
// Advertise the end of this connection
synchronized( pingLock ) {
if(pListener!=null){
pListener.pingComputed( NetPingListener.PING_CONNECTION_CLOSED );
pListener = null;
}
pingThread = null;
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
public synchronized void stopThread() {
shouldStopPingThread = true;
this.notify();
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
};
/*------------------------------------------------------------------------------------*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -