hello guys, ive been searching for ages on how to disconnect a client whether the request is from client or server but i cant find one. I thought the Naming.unbind() would do the trick but its not. anyway, this is my server code since I want to have my server a "kick" functionality to disconnect my clients..

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Vector;


public class Server extends UnicastRemoteObject implements Chat{
	
	Vector<Notify> clients = new Vector<Notify>();
	
	public Server() throws RemoteException{
		super();
	}
	
	public static void main(String args[]) throws Exception{
		Server server = new Server();
		String bind = "rmi://localhost:1099/DICMTRMI";
		System.out.println("Server started and binded to: " + bind);
		System.out.println("Waiting for client connections...");
		Naming.rebind(bind, server);
		
	}

	public void join(Notify n) throws RemoteException {
		clients.add(n);
		for(Iterator i = clients.iterator(); i.hasNext();){
			Notify notify = (Notify) i.next();
			notify.notifyJoine(n.getName());
		}
		System.out.println(n.getName() + " has joined the server.\n");
	}

	public void talk(Notify n, String message) throws RemoteException {
		for(Notify not : clients){
			not.notifySend(n.getName(), message);
		}
		System.out.println(n.getName() + ": " + message + "\n");
	}

	public void leave(Notify n) throws RemoteException {
		clients.remove(n);
		for(Iterator i = clients.iterator(); i.hasNext();){
			Notify notify = (Notify) i.next();
			notify.notifyLeave(n.getName());
		}
		System.out.println(n.getName() + ": has leaved the server.\n");
		lefts();
	}
	
	private void lefts() throws RemoteException{
		System.out.println("Clients left:\n");
		for(Notify not : clients){
			System.out.println(not.getName() + ",");
		}
		System.out.println("\n");
	}

}

Please inform me of what should I do.

Recommended Answers

All 2 Replies

I don't think there is a clean way of doing this in RMI given RMI doesn't offer an appropriate level of "socket" abstraction for this sort of stuff. Your best bet would be to pass a "callback handler" when "registering" or "joining" the chat. When the server wants to kick a client, it will just use the callback handler for that client (maybe stored in a Map at the server, name -> callback handler pair) to invoke the "kick" method. This kick() method will then be called in the "client JVM". In that method, you can "NULL" out the reference for the chat server.

Your client now no longer has the reference to the server and will have to make another call to "join" the chat. Just make sure you also call System.gc() and System.runFinalization() to ensure that the distributed garbage collector (DGC) kicks in and performs the necessary cleanup.

Some sample code:

public interface CommandHandler extends Remote {

    void kick() throws RemoteException;

}

public class CommandHandlerImpl extends UnicastremoteObject implements CommandHandler {

    private final Client client;

    public CommandHandlerImpl(Client client) {
        this.client = client;
    }

    public void kick() throws RemoteException {
        this.client.chatService = null;
        System.gc();
        System.runFinalization();
        System.out.println("You were kicked from the server, please reconnect!");
        
        // update UI by clearing out all text boxes, list boxes etc. so that the user gets
        // the impression that he was "actually" kicked out.
    }

}

// Your main application class which has the chat server reference and does all the UI stuff
public class Client extends JFrame {

    // remote service interface, the one which you lookup
    private volatile ChatService chatService = null;

    public static void main(final String[] args) {
        final Client client = new Client();
        client.init(); // look up chat server reference

        // all the methods which use chat server reference must first check
        // whether it is non-null. If it's NULL, it means that either this
        // is the first time the client is connecting to the server or the
        // client was forcefully kicked from the server (we can easily distinguish)
        // by setting a flag when "kick()" is called.
    }

}
commented: Nice solution. +16

@~s.o.s~, You saved my day :)) It works now! but i got another problem but not this topic. gotta post it later. thanks bro! this thread is solved.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.