java java中的RMI聊天程序-如何从客户端向客户端发送消息(不通过服务器)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10231588/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
RMI chat program in java - how to send mesage from client to client (not through the server)?
提问by Iyemwen
I cannot get the client to send a message to another client without going through the server. It is an obligatory school project that should be implemented like that. I would appreciate it if someone could help me.
我无法让客户端在不通过服务器的情况下向另一个客户端发送消息。这是一个必须这样实施的学校项目。如果有人可以帮助我,我将不胜感激。
Server Interface:
服务器接口:
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
public interface ChatServerInt extends Remote {
public abstract void register(ChatClientInt inClient) throws RemoteException;
public abstract ChatClientInt[] getClients() throws RemoteException;
public void disconnect(ChatClientInt client) throws RemoteException;
}
Server Implementation:
服务器实现:
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ChatServerImp extends UnicastRemoteObject implements ChatServerInt, Runnable {
private ChatClientInt[] clientList;
int counter = 0;
private ArrayList<String> connectedClients;
/**
* List of all registered remote clients.
*/
private List<ChatClientInt> clients = null;
/**
* Construct an instance of the chat server.
*/
public ChatServerImp() throws RemoteException {
// initialise the list of client objects.
clients = new ArrayList<ChatClientInt>();
connectedClients = new ArrayList<String>();
clientList = new ChatClientInt[16];
}
/**
* Register a chat client.
*/
public void register(ChatClientInt inClient) throws RemoteException {
// perform registration.
synchronized(clients)
{
clients.add(inClient);
clientList[counter++] = inClient;
inClient = new ChatClientImp();
for(int i = 0 ; i < clients.size();i++) {
System.out.println(inClient.getName()+ "has joined\n");
}
}
}
/**After registering, each client will request the list of connected users.
* Get a list of chat clients.
*/
public synchronized ChatClientInt[] getClients() throws RemoteException {
// generate and return the list
return clientList;
}
public void disconnect(ChatClientInt client) throws RemoteException {
for(int i = 0; i < clients.size(); i++) {
System.out.println(client.getName() + "" + "has joined \n");
}
clients.remove(client);
}
/**
* Generate a random subset. Based on an implementation of D. Knuth's
* @return
*/
private static <T> List<T> randomSample2(List<T> items, int m) {
Random rnd = new Random();
for(int i=0;i<items.size();i++){
int pos = i + rnd.nextInt(items.size() - i);
T tmp = items.get(pos);
items.set(pos, items.get(i));
items.set(i, tmp);
}
return items.subList(0, m);
}
/**
* Run the server's main thread. The server should periodically
* iterate through all registered clients to find out if they
* are still alive. Any dead clients will be removed from the
* client list.
*/
public void run() {
while(true) {
//System.out.println("waiting for client connection....\n");
// sleep for a while
try {
Thread.sleep(5000);
// iterate through all the clients we know. if we can't communicate with the client
// then eliminate it else if we can communicate with the client then do nothing.
for(int i =0; i < clients.size(); i++) {
try {
if(clients.get(i).getName()==null) {
clients.remove(clients.get(i).getName());
System.out.println("Disconnected clients:\n" + clients.get(i).getName());
}
}
catch (RemoteException e) {e.printStackTrace();}
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* Start the chat server.
* @param args
*/
public static void main(String[] args) throws Exception {
//ChatServerInt server;
try {
String serverName = "rmi://localhost/ChatServer";
// create an instance of the chat server
//server = (ChatServerImp) new ChatServerImp();
//Launch the registry - saves invoking it manually
java.rmi.registry.LocateRegistry.createRegistry(1099);
// register the instance with the RMIRegistry
Naming.rebind(serverName, new ChatServerImp());
//Naming.rebind(serverName, server);
// create the server thread and start it
//Thread t = new Thread(server).start();
System.out.println("Server running.....\n");
}
catch(RemoteException ex) {
System.out.println("Error binding the server to rmi");
}
}
}
Message Interface:
消息接口:
import java.util.HashSet;
public interface MessageInt {
/**
* Add a chat recipient to the list of receivers
* @param inClient
*/
public abstract void addRecipient(ChatClientInt inClient);
/**
* Get the set of clients that have seen this message
* @return
*/
public abstract HashSet<ChatClientInt> getRecipients();
/**
* Get the message content.
* @return
*/
public abstract String getContent();
/**
* Get an ID for a sender of the message
* @return
*/
public abstract String getSource();
}
Message Implementation:
消息实现:
import java.io.Serializable;
import java.util.HashSet;
public class MessageImp implements MessageInt, Serializable {
/**
*
*/
private static final long serialVersionUID = -2686034785384409672L;
HashSet<ChatClientInt> clientSet = new HashSet<ChatClientInt>();
String messageContent;
String messageSource;
public MessageImp(String inUser , String inMsg) {
messageSource = inUser;
messageContent = inMsg;
}
/**
* Add a chat recipient to the list of receivers
* @param inClient
*/
public void addRecipient(ChatClientInt inClient) {
synchronized(inClient) {
clientSet.add(inClient);
}
}
/**
* Get the set of clients that have seen this message
* @return
*/
public HashSet<ChatClientInt> getRecipients() {
return clientSet;
}
/**
* Get the message content.
* @return
*/
public String getContent() {
return messageContent;
}
/**
* Get an ID for a sender of the message
* @return
*/
public String getSource() {
return messageSource;
}
}
Client Interface:
客户端界面:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface ChatClientInt extends Remote {
/**
* Process a newly received message.
*
* @param inMessage
*/
public void processMessage(MessageInt inMessage)throws RemoteException;
/**
* Returns the name of the client.
*/
public String getName() throws RemoteException;
public boolean sendMessage(MessageInt inMessage) throws RemoteException;
}
Client Implementation:
客户端实现:
import java.io.Serializable;
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.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
public class ChatClientImp extends UnicastRemoteObject implements ChatClientInt, Runnable {
/**
*
*/
private static final long serialVersionUID = 74130345076834009L;
private ArrayList <String> eventHistory = new ArrayList<String>();
private HashSet<ChatClientInt> clientSet = new HashSet<ChatClientInt>();
private List<ChatClientInt> clients;// = new ArrayList<ChatClientInt>();
ChatClientInt[] listFromServer = new ChatClientInt[4];
String clientName;
String strMessage;
MessageInt messageObj;
ChatServerInt serverObj;
public ChatClientImp() throws RemoteException {
super();
clients = new ArrayList<ChatClientInt>();
}
public void processMessage(MessageInt inMessage) throws RemoteException {
System.out.println("message:" + inMessage.getRecipients().toString() + inMessage.getSource() + inMessage.getContent() + "\n");
}
public String getName() throws RemoteException {
return clientName;
}
public synchronized boolean sendMessage(MessageInt inMessage) throws RemoteException {
boolean success = false;
for(int i = 0; i < clients.size(); i++) {
clients.get(i).processMessage(inMessage);
inMessage.addRecipient(clients.get(i));
success = true;
}
return success;
}
public void displayMessage(String displayName, String displayMsg) {
Iterator<ChatClientInt> it = clientSet.iterator();
while(it.hasNext()) {
System.out.println(displayName + displayMsg + "\n");
}
}
public void run() {
Scanner scanner = new Scanner(System.in);
String userName = "";
try {
this.serverObj =(ChatServerInt) new ChatServerImp();
} catch (RemoteException e) {
e.printStackTrace();
}
// Keep requesting until a name is submitted that is not already used.
// checking for the existence of a name and adding the name
// is done while locking the set of names.
System.out.println("Please Enter a username\n");
while(true) {
userName = scanner.nextLine();
if(userName==null) {
return;
}
clientName = userName;
try {
serverObj.register(ChatClientImp.this);
listFromServer = serverObj.getClients();
clientSet.add(this);
} catch (RemoteException e) {
e.printStackTrace();
}
System.out.println("Hi" + " " + clientName + " " + "enter your message\n");
String msg = scanner.nextLine();
if(msg.equals("exit")) {
try {
serverObj.disconnect(this);
System.exit(0);
}
catch (RemoteException e) {
e.printStackTrace();
}
}//end if
if((listFromServer.length) > 1) {
System.out.println("list from client is" + " " + listFromServer.length + "going to try to send message.....\n");
try {
this.messageObj = new MessageImp(userName, msg);
boolean result = this.sendMessage(messageObj);
if(result) {
System.out.print("sending result is:" + result + "\n");
} else {
System.out.println("sending was not successful\n");
}
} catch (RemoteException e1) {
System.out.println("Error tryiing to send message from the Run()\n");
}
} else {
System.out.println("There is no one else logged on\n");
}
}
}
public static void main(String[] args) throws RemoteException {
String serverUrl= "rmi://localhost/ChatServer";
try {
ChatServerInt server = (ChatServerInt)Naming.lookup(serverUrl);
Thread thread = new Thread(new ChatClientImp());
thread.start();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
}
回答by user207421
The only way you can do that with RMI is if the clients are also RMI servers and send stubs to each other somehow.
您可以使用 RMI 做到这一点的唯一方法是,如果客户端也是 RMI 服务器并以某种方式相互发送存根。