Kryonet client disconnecting after timeout - java

My Kryonet server disconnects after 5000ms when I'm using this line for a connection
client.connect(5000, host, Network.port);
I thought the 5000 was the connection timeout but when I run the connection, it is able to connect and it receives the classes I send but it disconnects from the server after 5000ms.
I'm modifying the basic ChatClient.java provided with Kryonet.. Here's what I came up with.
import java.awt.EventQueue;
import java.io.IOException;
import com.badlogic.gdx.ApplicationListener;
import com.esotericsoftware.kryonet.Client;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.me.mygdxgame.Network.Obstacles;
public class GameClient implements ApplicationListener{
Client client;
String name;
public GameClient () {
client = new Client();
client.start();
// For consistency, the classes to be sent over the network are
// registered by the same method for both the client and server.
Network.register(client);
client.addListener(new Listener() {
public void connected (Connection connection) {
System.out.println("connected");
}
public void received (Connection connection, Object object) {
if (object instanceof Obstacles) {
Obstacles obs = (Obstacles)object;
System.out.println("Obstacle recieved on client - " + obs.obstacles.size());
return;
}else {
System.out.println("invalid packet");
}
}
public void disconnected (Connection connection) {
EventQueue.invokeLater(new Runnable() {
public void run () {
client.close();
// Closing the frame calls the close listener which will stop the client's update thread.
}
});
}
});
final String host = "localhost";
// We'll do the connect on a new thread so the ChatFrame can show a progress bar.
// Connecting to localhost is usually so fast you won't see the progress bar.
new Thread("Connect") {
public void run () {
try {
client.connect(5000, host, Network.port);
// Server communication after connection can go here, or in Listener#connected().
} catch (IOException ex) {
ex.printStackTrace();
System.exit(1);
}
}
}.start();
}
#Override
public void create() {
// TODO Auto-generated method stub
}
#Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void render() {
// TODO Auto-generated method stub
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
}

try to use client.SetKeepAliveTCP(int smallerthendisconnecttime);

The problem you are describing can arise if you configure your server for TCP and UDP but then have your client only connect via TCP.
If you're wanting to take advantage of the host discovery but only need a TCP connection thereafter then it is advisable that you "run a separate server for UDP discovery".
Basically, you need to be sure that client and server protocol usage matches (either both server and client are setup for only TCP, or both server and client are setup for both TCP and UDP).

Related

Connect socket server then send message using JAVA

I'm using Postman to test Chat feature (socket.io technology with version 2).
Currently, i have to implement Chat test cases using Java.
Postman request information:
1. Socket server: https://hc-socketio-example.xyz
2. Header.authorization: xxx
3. Header.source: app
4. Message.text with JSON format:
{ "ticketId": "63bcc910c22293b4b0495fe4", "content": "test ", "type": "text"}
My Java code to connect socket server:
URI uri = URI.create("https://hc-socket.unibag.xyz");
// #formatter:off
IO.Options options = IO.Options.builder().build();
// #formatter:on
Socket socket = IO.socket(uri, options);
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
System.out.println("Connected to server...");
}
});
socket.connect();
My issues need the help:
Look like my code gets wrong because no String "Connected to server..." printed.
I don't know the way to set the header or request: "authentication", "source"
I'm not sure the way to send JSON message like above:
COULD SOMEONE TAKE A LOOK AND GIVE ME THE ADVISE IN ORDER I COULD FIX MY CODE?
THANKS A LOT IN ADVANCE.
I tried researching on the internet some examples but no luck. I'm confusing about the way to send socket request.
Chats are typically facilitated through web sockets over http, assuming you want to build a chat system that runs over the internet.
I have a working program written that can establish a connection and send/receive messages from the Chat Server.
As a prerequisite you need a third party library.
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.3.0</version>
</dependency>
Also accompanied is the piece of client code that can send headers, get acknowledgement for connections and send/receive json messages
public class ChatWebSocketClient extends WebSocketClient{
public ChatWebSocketClient(URI serverURI, Map<String, String> headers) {
super(serverURI, new Draft_17(), headers, 0);
}
#Override
public void onOpen(ServerHandshake handshakedata) {
// TODO Auto-generated method stub
}
#Override
public void onMessage(String message) {
// TODO Auto-generated method stub
}
#Override
public void onClose(int code, String reason, boolean remote) {
// TODO Auto-generated method stub
}
#Override
public void onError(Exception ex) {
// TODO Auto-generated method stub
}
public static void main(String args[]) throws Exception {
Map<String, String> headers = new HashMap();
headers.put("header1", "value1 for header1");
ChatWebSocketClient client = new ChatWebSocketClient(new URI("Remote_Chat_EndPoint"), headers);
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
#Override
public X509Certificate[] getAcceptedIssuers() {
// TODO Auto-generated method stub
return new java.security.cert.X509Certificate[]{};
}
#Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// TODO Auto-generated method stub
}
#Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// TODO Auto-generated method stub
}
}};
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
client.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(sc));
client.connect();
client.send("{\"key\":\"Hello World\"}");
}
}

How to perform unit test on a server socket?

I am a beginner in Java. I have built a client-server group chat application watching tutorials. I read a lot about unit tests and can implement in simple maths problems but i don't know how does it work out for complex codes. So I want to see a demo of that which will make it easy to understand testing for rest parts. One part of the code is the 'server' class and it is:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
//import java.awt.event.*;
public class Server {
private final ServerSocket s;
public Server(ServerSocket serverSocket)
{
this.s = serverSocket;
//this.display = display;
}
public void startServer() {
try {
// Listen for connections (clients to connect) on port 1234.
while (!s.isClosed()) {
// Will be closed in the Client Handler.
Socket socket = s.accept();
System.out.println("A new client has connected!");
ClientHandler clientHandler = new ClientHandler(socket);
Thread thread = new Thread(clientHandler);
// The start method begins the execution of a thread.
// When you call start() the run method is called.
// The operating system schedules the threads.
thread.start();
}
} catch (IOException e) {
closeServerSocket();
}
}
// Close the server socket gracefully.
public void closeServerSocket() {
try {
if (s != null) {
s.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// Run the program.
public static void main(String[] args) throws IOException {
ServerSocket s = new ServerSocket(1234);
Server server = new Server(s);
server.startServer();
}
}
and the test I want to perform are:
import static org.junit.Assert.*;
public class ServerTeste {
#org.junit.Test
public void startServer() {
}
#org.junit.Test
public void closeServerSocket() {
f
}
}
#org.junit.Test
public void main() {
}
}
NB: Apologies for any mistake because I am complete beginner.
Start the server in a separate thread, and connect to it like you would normally do

Java RMI: how to make client stub method called on server print message on client screen?

I'm making a chat with rmi in Java. I have one server object and at least two clients objects. When a client send a message to the server calling the method recebeMensagem remotely, the server must print that message on all clients' screen (except the client that sent the message).
The client class has a method printMenssagem(Mensagem msg), that is called remotely by the server. The problem is that that method is printing on server's screen. How do I make to print the message on client's screen instead?
Server.java:
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.function.Predicate;
public class Server implements ChatServer {
private ArrayList<String> listaClientes = new ArrayList<>();
private static int port = 5002;
public static void main(String[] args) {
try {
Server obj = new Server();
ChatServer stub = (ChatServer)
UnicastRemoteObject.exportObject(obj, port);
// Bind the remote object's stub in the registry
Registry registry = LocateRegistry.createRegistry(port);
registry.bind("chat", stub);
System.out.println("Server ready!");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
#Override
public void adicionaCliente(String user) {
this.listaClientes.add(user);
}
#Override
public void retiraCliente(String userName) {
Predicate<String> clientePredicate = cp ->
cp.equals(userName);
listaClientes.removeIf(clientePredicate);
try {
Registry registry = LocateRegistry.getRegistry(port);
registry.unbind(userName);
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
#Override
public void recebeMensagem(Mensagem msg) {
try {
Registry registry = LocateRegistry.getRegistry(port);
for(String cliente : listaClientes) {
if (!cliente.equals(msg.getRemetente())) {
Client stub = (Client) registry.lookup(cliente);
stub.printMensagem(msg);
}
}
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
public ArrayList<String> getListaClientes() {
return listaClientes;
}
public void setListaClientes(ArrayList<String> listaClientes) {
this.listaClientes = listaClientes;
}
}
Client.java :
import java.io.Serializable;
import java.rmi.Remote;
public class Client implements Remote, Serializable {
private static final long serialVersionUID = 6864579049922061838L;
private static int port = 5002;
private static String host = "127.0.0.1";
public static void main(String[] args) {
new Thread(new ClientInterface(host, port)).start();
}
public void printMensagem(Mensagem mensagem) {
System.out.println(mensagem.getRemetente() + ": " + mensagem.getMensagem());
}
}
how to make client stub method called on server print message on client screen?
The client doesn't have a stub. It isn't a remote object. It is a serializable object and it has been transported to the Registry holus bolus, and it runs in whatever JVM performed the Registry.lookup() to obtain it. This is not what you want. You want it to be a remote object, with a stub, so you have to make it implement a remote interface, and export it, and use it via its remote interface at the peer.
You also need to be aware that your present architecture won't work across more than one host, as you can't bind to a remote Registry. You will need to add a client registration method to the server.

How can I put all network operations in single thread?

I am working with network so I have to use new thread.These my methods in SmackClass:
public void login(String username,String password) throws XMPPException, SmackException, IOException {
ConnectionConfiguration configuration=new ConnectionConfiguration("", 5222,"localhost");
configuration.setSecurityMode(SecurityMode.disabled);
connection=new XMPPTCPConnection(configuration);
connection.connect();
connection.login(username,password);
chatManager = ChatManager.getInstanceFor(connection);
chatManager.addChatListener(new ChatManagerListener() {
public void chatCreated(final Chat chat, final boolean createdLocally) {
chat.addMessageListener(messageListener);
}
});
}
public void sendMessage(String to,String message) throws NotConnectedException, XMPPException {
Chat chat=chatManager.createChat(to,messageListener);
chat.sendMessage(message);
}
I am calling above methods like this(in main class):
final SmackClass smack=new SmackClass();
Thread thread=new Thread() {
#Override
public void run() {
try {
smack.login("android","test");
} catch (XMPPException | SmackException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
thread.start();
try {
smack.sendMessage("pidgin#localhost", "test");
} catch (NotConnectedException | XMPPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
My application is giving nullPointerException for smack.sendMessage line because I am setting chatManager variable inside login method and this method is running in another thread.I know if I put smack.sendMessage line to inside this thread it will work.But I don't want to do this.Because I will use sendMessage method in another main class method.How can I resolve this problem ? I guess I need to do all network operations in single thread (not ui thread) but how ?
Easiest way is to implement a Queue. NetworkThread always look at queue if anything to process. Chat UI thread can put the command in to queue.
public class NetworkThread implements Runnable {
Queue<Command> queue;
public NetworkThread(Queue<Command> queue) throws IOException {
this.queue = queue;
}
public void run() {
while (true) {
Command command = queue.poll()
if(command != null){
command.execute();
}
}
}
}
Command is a interface you can define to implement each network operation.
interface Command{
public void execute();
}
class LoginCommand implements Command{
public void execute(){
//Do login operation
}
}
Now UI thread can push a Command Object in to queue, network thread will take care of executing it. Yo u may need to implement a message return mechanism in reverse direction as well.

How to implement the Observer pattern with Java RMI?

I have a client that starts a long running process on the server. At regular intervals, I'd like to show the user what's happening in the background. The most simple approach is to poll the server but I'm wondering if there wasn't a way to implement the Observer pattern for this. Unfortunately, I'm using RMI to talk to the server and I fear that I have to turn my client into an RMI server for this.
Is there another way that I'm missing?
http://sites.google.com/site/jamespandavan/Home/java/sample-remote-observer-based-on-rmi
RMI can in general support two way communication. (And yeah, RMI is a PITA to set up, and do anything else with.)
However, the HTTP transport that works over a CGI script(!) does not support it.
Consolidating all the answers here, I implemented 2 way RMI between client and server with server exposing its stub using Registry
The client gets a stub of the server from rmi registry
Then the client puts its stub as Observer to the server's addObserver method
The server notifies the clients using this stub
The following code will gives a better idea
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.Observable;
import java.util.Observer;
import java.net.*;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;
interface ReceiveMessageInterface extends Remote
{
/**
* #param x
* #throws RemoteException
*/
void receiveMessage(String x) throws RemoteException;
/**
* #param observer
* #throws RemoteException
*/
void addObserver(Remote observer) throws RemoteException;
}
/**
*
*/
class RmiClient extends UnicastRemoteObject
{
/**
* #param args
*/
static public void main(String args[])
{
ReceiveMessageInterface rmiServer;
Registry registry;
String serverAddress = args[0];
String serverPort = args[1];
String text = args[2];
System.out.println("sending " + text + " to " + serverAddress + ":" + serverPort);
try
{ // Get the server's stub
registry = LocateRegistry.getRegistry(serverAddress, (new Integer(serverPort)).intValue());
rmiServer = (ReceiveMessageInterface) (registry.lookup("rmiServer"));
// RMI client will give a stub of itself to the server
Remote aRemoteObj = (Remote) UnicastRemoteObject.exportObject(new RmiClient(), 0);
rmiServer.addObserver(aRemoteObj);
// call the remote method
rmiServer.receiveMessage(text);
// update method will be notified
}
catch (RemoteException e)
{
e.printStackTrace();
}
catch (NotBoundException e)
{
System.err.println(e);
}
}
public void update(String a) throws RemoteException
{
// update should take some serializable object as param NOT Observable
// and Object
// Server callsbacks here
}
}
/**
*
*/
class RmiServer extends Observable implements ReceiveMessageInterface
{
String address;
Registry registry;
/**
* {#inheritDoc}
*/
public void receiveMessage(String x) throws RemoteException
{
System.out.println(x);
setChanged();
notifyObservers(x + "invoked me");
}
/**
* {#inheritDoc}
*/
public void addObserver(final Remote observer) throws RemoteException
{
// This is where you plug in client's stub
super.addObserver(new Observer()
{
#Override
public void update(Observable o,
Object arg)
{
try
{
((RmiClient) observer).update((String) arg);
}
catch (RemoteException e)
{
}
}
});
}
/**
* #throws RemoteException
*/
public RmiServer() throws RemoteException
{
try
{
address = (InetAddress.getLocalHost()).toString();
}
catch (Exception e)
{
System.out.println("can't get inet address.");
}
int port = 3232;
System.out.println("this address=" + address + ",port=" + port);
try
{
registry = LocateRegistry.createRegistry(port);
registry.rebind("rmiServer", this);
}
catch (RemoteException e)
{
System.out.println("remote exception" + e);
}
}
/**
*
* #param args
*/
static public void main(String args[])
{
try
{
RmiServer server = new RmiServer();
}
catch (Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
}
I don't think you're missing anything. The only two ways are to either periodically call the server and check the status (polling) or register a callback which the server periodically calls (your client must expose a method). IMO, polling is a perfectly reasonable way to handle this.

Categories

Resources