Network error: com.jme3.network.kernel.ConnectorException: Connector closed.

Hi.

I’m trying to send an array from server to client,but when i try,it gives me a ConnectorException.

I checked if the serializer and listeners were registering in the same order and they do.

Server main:

[java]
@Serializable
public static class TextMessage extends AbstractMessage {
private String text;
public TextMessage() {}
public TextMessage(String txt) {
text=txt;
}

    public String getText() {             
        return text;
    }
}
@Serializable
public static class ArrayMessage extends AbstractMessage {
    protected ArrayList array;
    public ArrayMessage() {}
    public ArrayMessage(ArrayList arr) {
        array=arr;
    }
    
    public ArrayList getArray() {
        return array;
    }
}

   Serializer.registerClasses(TextMessage.class,ArrayMessage.class);
    srv.addMessageListener(new ServerListener(), TextMessage.class);
    srv.addMessageListener(new ServerListener(), ArrayMessage.class);[/java] 

Client main:
[java]
@Serializable
public static class TextMessage extends AbstractMessage {
private String text;
public TextMessage() {}
public TextMessage(String txt) {
text=txt;
}

    public String getText() {             
        return text;
    }
}

@Serializable
public static class ArrayMessage extends AbstractMessage {
    private ArrayList array;
    public ArrayMessage() {}
    public ArrayMessage(ArrayList arr) {
        array=arr;
    }
    
    public ArrayList getArray() {
        return array;
    }
}
  Serializer.registerClasses(TextMessage.class,ArrayMessage.class);
        client.addMessageListener(new ClientListener(), TextMessage.class);
        client.addMessageListener(new ClientListener(), ArrayMessage.class);[/java] 

Client listener:

[java]public class ClientListener implements MessageListener<Client> {
@Override
public void messageReceived(Client src,Message msg) {
if(msg instanceof TextMessage) {
msg.setReliable(true);
String packet=((TextMessage) msg).getText();
System.out.println(packet);
}
else if(msg instanceof ArrayMessage) {
msg.setReliable(true);
ArrayList packet=((ArrayMessage) msg).getArray();
switch(packet.get(0).toString()) {
case “ItemList” : System.out.println(packet);
break;
}
}
}
}
[/java]

Server Listener:

[java]public class ServerListener implements MessageListener<HostedConnection>{
@Override
public void messageReceived(HostedConnection src,Message msg) {
if(msg instanceof TextMessage) {
msg.setReliable(true);
String packet=((TextMessage) msg).getText();
switch(packet) {
case “RequestItemList” : Main.getServer().broadcast(Filters.in(src),new ArrayMessage(Main.getItemList()));
System.out.println("Sent item list to: "+src);
System.out.println(Main.getItemList());
break;
}
}
else if(msg instanceof ArrayMessage) {
msg.setReliable(true);
ArrayList packet=((ArrayMessage) msg).getArray();
switch(packet.get(0).toString()) {
case “ItemList” : System.out.println(packet);
break;
}
}
}
}[/java]

I don’t get this with TextMessage.

Can someone help me?i’m not an expert with network programming and that’s my first attempt in it.
[java][/java] [java][/java] [java][/java] [java][/java] [java][/java]

The serializers are obviously in the main() method in both client and server.

If the connection is closed then it’s because there was an error on the other end.

http://hub.jmonkeyengine.org/javadoc/com/jme3/network/Client.html#addErrorListener(com.jme3.network.ErrorListener)

ArrayMessage and TextMessage should be classes on their own.
And there should be a NetworkUtil class where you register the message classes and have the client and server use it for registering.
You are really looking for trouble by doing otherwise. This is not me being more catholic than the pope, it’s really the stuff of nightmares otherwise.

Does TextMessage work?

@loopies said: ArrayMessage and TextMessage should be classes on their own.

They don’t have to be classes on their own. They just have to be static and have a no-arg constructor. Otherwise, static classes are ‘classes on their own’ for the sake of this discussion.

When we can see what the actual error is then we work back from there. Error listeners are important.

But note: I think if you try to send message 2 and get a ‘connection closed’ error then the actual drop happened because of message 1.

Edit: you probably also want a connection listener on the server to see when connections drop.

… until one of the message class is modified and not it’s counterpart :D.

@loopies said: ... until one of the message class is modified and not it's counterpart :D.

I assumed they were static inner classes of a shared class… then it’s fine.

If they are static inner classes of two different classes then that’s the problem. That can’t possibly work because they are totally different classes then.

Edit: and thus the problem when people don’t want to show anything but the absolute minimum of code. :-/

Yah, was suspecting wouldn’t work which is why I was wondering if sending a TextMessage worked.
His snippets do point towards them being static inner classes of his Client and Server classes.

@loopies said: Yah, was suspecting wouldn't work which is why I was wondering if sending a TextMessage worked. His snippets do point towards them being static inner classes of his Client and Server classes.

Yeah, you’re right about the way he posted it. If so then they aren’t even the same classes.

To OP: if what this discussion has ferreted out is true then your issue is that Client.TextMessage is a totally and entirely different class than Server.TextMessage… and while Spider Monkey’s serializer is blind enough to allow this almost to work some of the time, it is a super bad practice and it likely to break in strange ways at any time.

Server and Client are 2 different applications,but TextMessage works.

@aegroto said: Server and Client are 2 different applications,but TextMessage works.

Apparently not since the client is already long dead by the time you try and send the second message. Messages are sent asynchronously so if you try to send a message and get a disconnected exception then it died a while back.

Client and server can be two different applications but they should share a common set of classes. To do otherwise is extremely dangerous and you will have nothing but problems in the long run.

@pspeed said: Apparently not since the client is already long dead by the time you try and send the second message. Messages are sent asynchronously so if you try to send a message and get a disconnected exception then it died a while back.

Client and server can be two different applications but they should share a common set of classes. To do otherwise is extremely dangerous and you will have nothing but problems in the long run.

Ok,so i’ll try to make a package with shared classes,thanks.

@aegroto said: Ok,so i'll try to make a package with shared classes,thanks.

Also, follow all of the other advice in this thread, re: error listeners, connection listeners, etc…

There is a decent chance that this issue has nothing at all to do with serialization.

Also, why are you doing this to your received messages:
msg.setReliable(true);

…that controls how they are sent… it is meaningless once they have been received.

And while I’m critiquing:
Main.getServer().broadcast(Filters.in(src),new ArrayMessage(Main.getItemList()))

…is the really super long way of saying:
src.send(new ArrayMessage(Main.getItemList())

But textmessage works,so it has nothing to do with sharing the classes too.

Any other suggestions?

@aegroto said: But textmessage works,so it has nothing to do with sharing the classes too.

Any other suggestions?

Tons… you just have to read and follow them. See like all of the above messages.

I’m done responding to this thread until you follow even one suggestion I’ve given so far.

I already made what you said,i created another packaged for the server and then implemented the same classes in both client and server package,but it still gives me the same error about ConnectorAdapter.

@pspeed said: They don't have to be classes on their own. They just have to be static and have a no-arg constructor. Otherwise, static classes are 'classes on their own' for the sake of this discussion.

When we can see what the actual error is then we work back from there. Error listeners are important.

But note: I think if you try to send message 2 and get a ‘connection closed’ error then the actual drop happened because of message 1.

Edit: you probably also want a connection listener on the server to see when connections drop.

@pspeed said: Also, follow all of the other advice in this thread, re: error listeners, connection listeners, etc...

There is a decent chance that this issue has nothing at all to do with serialization.

I tried without being making them classes on their own too,and the connection drops when the server tries to serialize the array:

[java]Grave: Unhandled error, endpoint:NioEndpoint[1, java.nio.channels.SocketChannel[connected local=/127.0.0.1:1337 remote=/127.0.0.1:61746]], context:groteserver.TextMessage@291a59e3
java.lang.RuntimeException: Error serializing message
at com.jme3.network.base.MessageProtocol.messageToBuffer(MessageProtocol.java:81)
at com.jme3.network.base.DefaultServer$Connection.send(DefaultServer.java:487)
at groteserver.ServerListener.messageReceived(ServerListener.java:23)
at groteserver.ServerListener.messageReceived(ServerListener.java:16)
at com.jme3.network.base.MessageListenerRegistry.messageReceived(MessageListenerRegistry.java:73)
at com.jme3.network.base.DefaultServer.dispatch(DefaultServer.java:282)
at com.jme3.network.base.DefaultServer$Redispatch.messageReceived(DefaultServer.java:569)
at com.jme3.network.base.DefaultServer$Redispatch.messageReceived(DefaultServer.java:565)
at com.jme3.network.base.KernelAdapter.dispatch(KernelAdapter.java:183)
at com.jme3.network.base.KernelAdapter.createAndDispatch(KernelAdapter.java:237)
at com.jme3.network.base.KernelAdapter.run(KernelAdapter.java:280)
Caused by: com.jme3.network.serializing.SerializerException: Error writing object for field:private java.util.ArrayList groteserver.ArrayMessage.array
at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:180)
at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:389)
at com.jme3.network.base.MessageProtocol.messageToBuffer(MessageProtocol.java:73)
… 10 more
Caused by: java.lang.IllegalArgumentException: Class has not been registered:class groteserver.Item
at com.jme3.network.serializing.Serializer.getSerializerRegistration(Serializer.java:324)
at com.jme3.network.serializing.Serializer.getSerializerRegistration(Serializer.java:293)
at com.jme3.network.serializing.Serializer.writeClass(Serializer.java:368)
at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:388)
at com.jme3.network.serializing.serializers.CollectionSerializer.writeObject(CollectionSerializer.java:109)
at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:389)
at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:175)
… 12 more
[/java]

“SerializerException: Error writing object for field:private java.util.ArrayList”

Try making your ArrayList field public in the array message class.