📄 netserver.java
字号:
*
* @return a new AsynchronousNetConnection associated to this socket.
*/
protected NetConnection getNewConnection( Socket socket ) throws IOException{
return new AsynchronousNetConnection( socket );
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Sends a message to tell a client that he is welcome on this server.
* Should be called by initializeConnection() if you decide to accept the client.
*
* @param connection a previously created connection for this connection.
*/
protected void acceptClient( NetConnection connection ) {
connection.queueMessage( new ServerWelcomeMessage() );
connection.sendAllMessages();
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Sends a message to tell a client that he is refused on this server.
* Should be called by initializeConnection() if you decide to refuse the client.
*
* @param connection a previously created connection for this connection.
* @param errorMessage error message to send
*/
protected void refuseClient( NetConnection connection, short errorCode, String errorMessage ) {
connection.queueMessage( new ServerErrorMessage( errorCode, errorMessage ) );
connection.close();
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Server Thread Runtime.
* Never call this method it's done automatically.
*/
public void run() {
Socket clientSocket; // current socket
NetConnection connection; // current connection object wrapping up the socket
boolean failureOccured = false; // if a failure already occured during the accept()
// We retrieve a valid server socket. This method can lock to wait for the itf to get ready.
server = getServerSocket();
// We print some info about this server.
Debug.signal( Debug.NOTICE, null, "Starting Server on "+server.getInetAddress()+":"+server.getLocalPort() );
// We wait for client connections. We catch exceptions at different levels because
// their importance is linked to where they are thrown.
while( !mustStop() ) {
clientSocket = null;
connection = null;
try{
// we wait 5s for clients (InterruptedIOException after)
clientSocket = server.accept();
}
catch(InterruptedIOException iioe) {
// This is the normal behaviour : the SOTimeout was fired
failureOccured = false;
server = getServerSocket(); // we update our server socket if needed
continue;
}
catch( Exception e ){
Debug.signal( Debug.FAILURE, this, e );
if(failureOccured)
Debug.exit(); // this was our second try, we quit...
else {
failureOccured = true;
continue; // retry... one more time only
}
}
// Ok, a client has arrived.
try{
// We creates a connection object to take care of him...
connection = getNewConnection( clientSocket );
// we inspect our server state... can we really accept him ?
if( !registerConnection( connection ) ) {
// we have reached the server's connections limit
refuseClient( connection, ERR_MAX_CONN_REACHED, "Server has reached its maximum number of connections for the moment." );
Debug.signal(Debug.NOTICE,this,"Err:"+ERR_MAX_CONN_REACHED+" - Server has reached its max number of connections");
}
else if(serverLock) {
// we don't accept new connections for the moment
refuseClient( connection, ERR_ACCESS_LOCKED, "Server does not accept connections for the moment." );
Debug.signal(Debug.NOTICE,this,"Err:"+ERR_ACCESS_LOCKED+" - Server Locked - just refused incoming connection");
}
else {
// we can start this connection and inspect the client connection.
// the context provided is an helper for the NetClientRegisterMessage
// behaviour.
connection.setContext( (Object) new NetServerEntry( this, connection ) );
connection.start();
}
}
catch(IOException ioe) {
// there was an error while dealing with this new client
// we continue as if nothing had happened
Debug.signal( Debug.ERROR, this, ioe );
}
}
// We close the server connection
try{
server.close();
Debug.signal( Debug.NOTICE, this, "Server Stopped." );
}
catch(IOException e) {
Debug.signal( Debug.WARNING, this, e );
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To set or unset the server lock.
* @param lock server lock new value
*/
public void setServerLock( boolean lock ) {
serverLock = lock;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To stop this server
*/
synchronized public void stopServer(){
stopServer = true;
notifyAll();
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** should we stop ?
* @return true if the server must stop.
*/
synchronized private boolean mustStop(){
return stopServer;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To change the maximum number of opened sockets. This can be refused if more than
* the new 'maxOpenedSockets' are already opened.
* @param maxOpenedSockets maximum number of opened sockets
*/
protected synchronized void setMaximumOpenedSockets( int maxOpenedSockets ) {
// 1 - can we accept this request ?
int nb=0;
for(int i=0; i<connections.length; i++)
if(connections[i]!=null)
nb++;
if( nb>maxOpenedSockets ) {
Debug.signal(Debug.ERROR,this,"setMaximumOpenedSockets() Request refused : more sockets are already opened !");
return;
}
// 2 - ok, request accepted
this.maxOpenedSockets = maxOpenedSockets;
NetConnection tmp[] = new NetConnection[maxOpenedSockets];
nb=0;
for(int i=0; i<connections.length; i++)
if(connections[i]!=null) {
tmp[nb] = connections[i];
nb++;
}
connections = tmp; // swap
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To add a NetServerListener on this connection.
* The listener will receive information on the life on our network interface.
* @param listener an object implementing the NetServerListener interface.
*/
public void addServerListener( NetServerListener listener ) {
NetServerListener tmp[] = new NetServerListener[listeners.length+1];
for( int i=0; i<listeners.length; i++ )
tmp[i] = listeners[i];
tmp[tmp.length-1]= listener;
listeners = tmp;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To remove the specified server listener.
* @param listener listener to remove.
* @return true if the listener was removed, false if it was nor found
*/
public boolean removeServerListener( NetServerListener listener ) {
// does the listener exists ?
boolean found = false;
for( int i=0; i<listeners.length; i++ )
if( listeners[i]==listener ) {
found = true;
break;
}
if( !found )
return false; // not found
// We remove the connection listener
NetServerListener tmp[] = new NetServerListener[listeners.length-1];
int nb=0;
for( int i=0; i<listeners.length; i++ )
if( listeners[i]!=listener ) {
tmp[nb]=listeners[i];
nb++;
}
listeners = tmp;
return true;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** This method is called when a new network connection is created for you.
* @param connection the NetConnection object associated to this connection.
*/
public synchronized void connectionCreated( NetConnection connection ) {
// we add this connection to our list
for( int i=0; i<connections.length; i++ )
if(connections[i]==null) {
connections[i] = connection;
return;
}
// ERROR !!! should never happen
Debug.signal(Debug.ERROR,this,"Failed to find room for established connection !! closing it !");
connection.close();
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** This method is called when the network connection is no longer of this world.
* @param connection the NetConnection object associated to this connection.
*/
public synchronized void connectionClosed( NetConnection connection ) {
// we remove this connection from our list
for( int i=0; i<connections.length; i++ )
if(connections[i]==connection) {
connections[i] = null;
return;
}
// ERROR !!! should never happen !
Debug.signal(Debug.ERROR,this,"Failed to find connection in our list ! an error must have occured...");
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Tries to register a new connection in our list.
* @param connection the NetConnection object associated to this connection.
*/
public synchronized boolean registerConnection( NetConnection connection ) {
// we try to find some room for the new connection
for( int i=0; i<connections.length; i++ )
if(connections[i]==null) {
connection.addConnectionListener( this ); // this way the registration will not
return true; // occur if the connection has been closed roughly
}
return false; // no room, sorry !
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Closes all the connections on this server.
*/
public synchronized void closeConnections() {
for( int i=0; i<connections.length; i++ )
if(connections[i]!=null)
connections[i].close();
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Sends a NetMessage to all the connections on this server.
* @param msg a net message to send to all clients.
*/
public synchronized void sendMessageToOpenedConnections( NetMessage msg ) {
for( int i=0; i<connections.length; i++ )
if(connections[i]!=null)
connections[i].queueMessage( msg );
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -