푸시 구성으로 RMI를 사용하여 간단한 채팅 프로그램을 만들려고합니다. 이 프로그램은 내부 네트워크에서 작동하지만, 외부 네트워크에있는 서버에 프로그램을 실행하려고 할 때, 우리는 오류 얻을 :외부 네트워크에서 RMI Chat 프로그램 푸시 구성이 작동하지 않습니다.
java.rmi.ConnectException: Connection refused to host: 192.168.1.13;
Caused by: java.net.ConnectException: Connection timed out: connect
클라이언트가 방법 '방송을 호출 할 때 오류가 발생합니다 (문자열 s ')'IChatServer '인터페이스 이 메서드는 서버에 있으며 서버의 수신기로 구독 된 다른 클라이언트를 호출합니다.
클라이언트가 서버에 연결할 수 있습니다. 레지스트리에서 바인딩을 가져 와서 서버에서 메소드를 호출 할 수 있습니다.
그러나 서버가 클라이언트에서 메서드를 호출하려고하면이 오류가 발생합니다.
서버에서는 포트 1099가 전달되고 포트 1099는 방화벽에서 허용됩니다.
(RMI를 사용하여)이를 가능하게하는 방법이 있습니까? 또는 클라이언트 측의 포트를 전달해야합니까?
서버 :
try {
String theIp = serverHostExternalIp;
System.setProperty("java.rmi.server.hostname", theIp);
//Implemented this so no random ports will be used
RMISocketFactory.setSocketFactory(new FixedPortRMISocketFactory());
registry = LocateRegistry.createRegistry(PORT_NUMBER);
publisher = new RemotePublisher();
publisher.registerProperty(BINDING_NAME);
UnicastRemoteObject.unexportObject(server, true);
UnicastRemoteObject.exportObject(server, PORT_NUMBER);
UnicastRemoteObject.unexportObject(publisher, true);
UnicastRemoteObject.exportObject(publisher, PORT_NUMBER);
registry.rebind(BINDING_NAME, server);
registry.rebind(PUBLISH_NAME, publisher);
} catch (RemoteException ex) {
System.err.println("[Server] Cannot bind student administration");
System.err.println("[Server] RemoteException: " + ex.getMessage());
}
IChatServer :
public synchronized void tryConnect(String s, IChatClient client) throws RemoteException {
System.out.println("[Server] User connected: " + s);
}
public synchronized void broadcast(String s) throws RemoteException {
// When this line is called, no errors occur, and the string is printed correctly.
System.out.println("[Message] " + s);
//on this line, the server tries to reach to all the clients (all listeners)
//This line of code will generate an error.
publisher.inform(BINDING_NAME, null, s);
}
클라이언트 : RMI의 방식에 대한
try {
registry = LocateRegistry.getRegistry(ipAddress, PORT_NUMBER);
mycs = (IChatServer) registry.lookup(BINDING_NAME);
//This method is located on the server and is called without errors.
mycs.tryConnect(userid, this);
publisher = (IRemotePublisherForListener) registry.lookup(PUBLISH_NAME);
publisher.subscribeRemoteListener(this, BINDING_NAME);
} catch (RemoteException ex) {
System.err.println("[Client] Cannot lookup or subscribe publisher");
System.err.println("[Client] RemoteException: " + ex.getMessage());
registry = null;
} catch (NotBoundException e) {
System.err.println("[Client] Cannot lookup or subscribe publisher");
System.err.println("[Client] NotBoundException: " + e.getMessage());
registry = null;
}
그래서 양방향 연결이 되었습니까? 클라이언트는 서버에서 메소드를 호출 할 수 있으며 그 반대도 가능합니다. – Antoniossss
@Antoniossss 예, 채팅 프로그램을 만드는 가장 좋은 방법은 아닙니다. 클라이언트가 메시지를 보내는 서버에 알려주고, 서버가 다른 모든 클라이언트에게 메시지를 브로드 캐스트하기위한 것이 필요합니다. 적어도 그것은 그것이 내가 이해하고있는 것입니다. – Wilmz
일반적으로 RMI는 일반적인 PULL이지만 PUSH 아키텍처가 필요합니다. 바퀴를 재발 명하면서, 기존의 XMPP처럼 채팅과 유사한 채팅 기술에 기존 기술을 자유롭게 사용하는 이유는 무엇입니까? 과거에는 XMPP 기반의 채팅 응용 프로그램을 만들고 메시지 브로커로 OpenFire 서버를 사용했습니다. 메시지 대기열을 사용하여 채팅 응용 프로그램의 용도로 PUSH 아키텍처를 구현할 수도 있습니다. – Antoniossss