Captive Imagination
September 06, 2010, 09:09:52 AM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: Hosting change completed. Please send an e-mail to support@captiveimagination.com if you have any problems.
 
   Home   Help Search Calendar Login Register  
Pages: [1]   Go Down
  Print  
Author Topic: Having problems getting my connection to work  (Read 891 times)
0 Members and 1 Guest are viewing this topic.
ractoc
Newbie
*
Offline Offline

Posts: 8


View Profile
« on: November 21, 2009, 07:42:47 AM »

Hello all,

I'm pretty new to JGN and I'm having problems getting my connection to work right.
I was working on a ServerConnector and a ClientConnector based off of the BasicServer and BasicCLient. But I kept running into the problem that my connected() method wasn't executed on either the server or the client.
After trying the BasicServer/BasicClient themselves, I hit exactly the same problem. I'm running VISTA if this may be part of the problem...

I really hope you guys can get me sorted here, cause without being able to even get the connection online, the rest of the library is kind of useless....

Mark
Logged
darkfrog
Administrator
Inspired Imagination
*****
Offline Offline

Posts: 2650


View Profile
« Reply #1 on: November 22, 2009, 07:24:01 AM »

Have you run any of the tests?  Do they have similar problems?
Logged
ractoc
Newbie
*
Offline Offline

Posts: 8


View Profile
« Reply #2 on: November 22, 2009, 07:30:11 AM »

I ran the chat server/clent test case, which did work. But this doesn't use the connected methods.
I also tried basing my code on that, but when I try to send a message, I get the error that the connection has already been closed.
Logged
Tumaini
JGN Developer
Jr. Member
*****
Offline Offline

Posts: 51


View Profile
« Reply #3 on: November 22, 2009, 02:49:26 PM »

Have you got any code you could show, how you've done it in the case where it doesn't work?
Logged
ractoc
Newbie
*
Offline Offline

Posts: 8


View Profile
« Reply #4 on: November 23, 2009, 12:17:39 PM »

Client code:

here the BaseConnector, MessagePublisher and MessageSubscriber are class and interfaces within JGF.
Code:
package net.jgf.network.client;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;

import net.jgf.config.Config;
import net.jgf.config.Configurable;
import net.jgf.console.bean.ChatBean;
import net.jgf.messaging.BaseJGFMessage;
import net.jgf.messaging.MessageBroker;
import net.jgf.messaging.MessageNotifications;
import net.jgf.messaging.MessagePublisher;
import net.jgf.messaging.MessageSubscriber;
import net.jgf.network.messages.JGNChatMessage;
import net.jgf.network.messages.JGNMessage;
import net.jgf.network.server.BaseConnector;
import net.jgf.network.translators.TranslatorMap;
import net.jgf.system.Jgf;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.captiveimagination.jgn.JGN;
import com.captiveimagination.jgn.clientserver.JGNClient;
import com.captiveimagination.jgn.clientserver.JGNConnection;
import com.captiveimagination.jgn.clientserver.JGNConnectionListener;
import com.captiveimagination.jgn.event.MessageListener;
import com.captiveimagination.jgn.message.Message;

/**
 * Responsible for setting up and maintaining the connection to a single server.
 * If connections to different servers are needed, more instances of this class
 * need to be added to the config.
 * @author Schrijver
 * @version 1.0
 */
@Configurable
public class ClientConnector extends BaseConnector implements MessagePublisher, MessageSubscriber, MessageListener,
        JGNConnectionListener {

    /**
     * Class logger.
     */
    private static final Logger logger              = Logger.getLogger(ChatBean.class);

    private JGNClient           client;

    private String              bindAddressReliable = "127.0.0.1";

    private Integer             bindPortReliable    = 10000;

    private String              bindAddressFast     = "127.0.0.1";

    private Integer             bindPortFast        = 20000;

    private Integer             timeout             = 5000;

    private Integer             maxPackets          = 60;

    private MessageBroker       messageBroker;

    /**
     * Constructor.
     */
    public ClientConnector() {
    }

    @Override
    public void readConfig(Config config, String configPath) {

        super.readConfig(config, configPath);

        String baReliable = config.getString(configPath + "/bindaddress[@type='reliable']");
        if (StringUtils.isNotEmpty(baReliable)) {
            bindAddressReliable = baReliable;
        }
        String bpReliable = config.getString(configPath + "/bindport[@type='reliable']");
        if (StringUtils.isNotEmpty(bpReliable)) {
            bindPortReliable = new Integer(bpReliable);
        }
        String baFast = config.getString(configPath + "/bindaddress[@type='fast']");
        if (StringUtils.isNotEmpty(baFast)) {
            bindAddressFast = baFast;
        }
        String bpFast = config.getString(configPath + "/bindport[@type='fast']");
        if (StringUtils.isNotEmpty(bpFast)) {
            bindPortFast = new Integer(bpFast);
        }
        String to = config.getString(configPath + "/timeout");
        if (StringUtils.isNotEmpty(to)) {
            timeout = new Integer(to);
        }
        String mPackets = config.getString(configPath + "/maxpackets");
        if (StringUtils.isNotEmpty(mPackets)) {
            maxPackets = new Integer(mPackets);
        }

        if (config.containsKey(configPath + "/messagebroker/@ref")) {
            String messageBrokerRef = config.getString(configPath + "/messagebroker/@ref");
            messageBroker = Jgf.getDirectory().getObjectAs(messageBrokerRef, MessageBroker.class);
            messageBroker.registerMessagePublisher(this);
            int index = 1;
            while (config.containsKey(configPath + "/messagebroker/subscription[" + index + "]/@topic")) {
                String topic = config.getString(configPath + "/messagebroker/subscription[" + index + "]/@topic");
                messageBroker.registerMessageSubscriber(this, topic);
                index++;
            }
        }
    }

    /**
     * @return the bindAddressReliable
     */
    public final String getBindAddressReliable() {
        return bindAddressReliable;
    }

    /**
     * @param bindAddressReliable the bindAddressReliable to set
     */
    public final void setBindAddressReliable(String bindAddressReliable) {
        this.bindAddressReliable = bindAddressReliable;
    }

    /**
     * @return the bindPortReliable
     */
    public final Integer getBindPortReliable() {
        return bindPortReliable;
    }

    /**
     * @param bindPortReliable the bindPortReliable to set
     */
    public final void setBindPortReliable(Integer bindPortReliable) {
        this.bindPortReliable = bindPortReliable;
    }

    /**
     * @return the bindAddressFast
     */
    public final String getBindAddressFast() {
        return bindAddressFast;
    }

    /**
     * @param bindAddressFast the bindAddressFast to set
     */
    public final void setBindAddressFast(String bindAddressFast) {
        this.bindAddressFast = bindAddressFast;
    }

    /**
     * @return the bindPortFast
     */
    public final Integer getBindPortFast() {
        return bindPortFast;
    }

    /**
     * @param bindPortFast the bindPortFast to set
     */
    public final void setBindPortFast(Integer bindPortFast) {
        this.bindPortFast = bindPortFast;
    }

    /**
     * @return the timeout
     */
    public final Integer getTimeout() {
        return timeout;
    }

    /**
     * @param timeout the timeout to set
     */
    public final void setTimeout(Integer timeout) {
        this.timeout = timeout;
    }

    /**
     * @return the maxPackets
     */
    public final Integer getMaxPackets() {
        return maxPackets;
    }

    /**
     * @param maxPackets the maxPackets to set
     */
    public final void setMaxPackets(Integer maxPackets) {
        this.maxPackets = maxPackets;
    }

    @Override
    public void connect() throws IOException {
        try {
            JGN.register(JGNChatMessage.class);
            client = new JGNClient();
            // client.addMessageListener(this);
            // client.addMessageListener(new DebugListener("ChatClient>"));
            client.addServerConnectionListener(this);
            JGN.createThread(client).start();

            InetSocketAddress reliableServerAddress = new InetSocketAddress(InetAddress.getByName(bindAddressReliable),
                    bindPortReliable);
            InetSocketAddress fastServerAddress = new InetSocketAddress(InetAddress.getByName(bindAddressFast),
                    bindPortFast);
            client.connectAndWait(reliableServerAddress, fastServerAddress, timeout);
            System.out.println("client is connected.");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            throw new IOException("Unable to connect, connection timed out.", e);
        }
    }

    @Override
    public void disconnect() {
        try {
            client.disconnect();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void messageCertified(Message message) {
        // TODO Auto-generated method stub

    }

    @Override
    public void messageFailed(Message message) {
        // TODO Auto-generated method stub

    }

    @Override
    public void messageReceived(Message message) {
        BaseJGFMessage jgfMessage = (BaseJGFMessage) TranslatorMap.translate(message);
        if (jgfMessage != null) {
            jgfMessage.setTopic(jgfMessage.getMessageCategory() + "_received");
            messageBroker.publishMessage(jgfMessage, this.getId());
        }
    }

    @Override
    public void messageSent(Message message) {
        // TODO Auto-generated method stub

    }

    private void sendMessage(BaseJGFMessage jgfMessage) {
        // ((JGFChatMessage) jgfMessage).setText("loopback - " +
        // ((JGFChatMessage) jgfMessage).getText());
        JGNMessage jgnMessage = (JGNMessage) TranslatorMap.translate(jgfMessage);
        // this step needs to be done manually since the playerId in the
        // JGNMessage is used by JGN for other purposes already.
        jgnMessage.setPlayerKey(jgfMessage.getPlayerId());
        client.sendToServer(jgnMessage);
        // messageReceived(jgnMessage);
    }

    @Override
    public void receiveNotification(BaseJGFMessage message, MessageNotifications notification) {
        if (notification == MessageNotifications.NO_SUBSCRIBERS) {
            logger.debug("No subscribers defined");
        }
    }

    @Override
    public void receiveMessage(BaseJGFMessage message) {
        sendMessage(message);
    }

    @Override
    public void connected(JGNConnection connection) {
        System.out.println("logged in as Player " + connection.getPlayerId());
    }

    @Override
    public void disconnected(JGNConnection connection) {
        System.out.println("logged off");
    }
}

Server:
Here BaseConnector, MessagePublisher and MessageSubscriber are class and interfaces from within JGF.
Code:
package net.jgf.network.server;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

import net.jgf.config.Config;
import net.jgf.config.Configurable;
import net.jgf.console.bean.ChatBean;
import net.jgf.messaging.BaseJGFMessage;
import net.jgf.messaging.MessageBroker;
import net.jgf.messaging.MessageNotifications;
import net.jgf.messaging.MessagePublisher;
import net.jgf.messaging.MessageSubscriber;
import net.jgf.network.messages.JGNChatMessage;
import net.jgf.network.messages.JGNMessage;
import net.jgf.network.translators.TranslatorMap;
import net.jgf.system.Jgf;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.captiveimagination.jgn.JGN;
import com.captiveimagination.jgn.clientserver.JGNConnection;
import com.captiveimagination.jgn.clientserver.JGNConnectionListener;
import com.captiveimagination.jgn.clientserver.JGNServer;
import com.captiveimagination.jgn.event.MessageListener;
import com.captiveimagination.jgn.message.Message;

/**
 * Responsible for listening to client connections.
 * @author Schrijver
 * @version 1.0
 */
@Configurable
public class ServerConnector extends BaseConnector implements MessagePublisher, MessageSubscriber, MessageListener,
        JGNConnectionListener {

    /**
     * Class logger.
     */
    private static final Logger   logger              = Logger.getLogger(ChatBean.class);

    private String                bindAddressReliable = "127.0.0.1";

    private Integer               bindPortReliable    = 10000;

    private String                bindAddressFast     = "127.0.0.1";

    private Integer               bindPortFast        = 20000;

    private Integer               timeout             = 5000;

    private Integer               maxPackets          = 60;

    private MessageBroker         messageBroker;

    private JGNServer             server;

    private Map < Short, String > clientIds           = new HashMap < Short, String >();

    private Map < String, Short > playerIds           = new HashMap < String, Short >();

    /**
     * Constructor.
     */
    public ServerConnector() {
    }

    @Override
    public void readConfig(Config config, String configPath) {

        super.readConfig(config, configPath);

        String baReliable = config.getString(configPath + "/bindaddress[@type='reliable']");
        if (StringUtils.isNotEmpty(baReliable)) {
            bindAddressReliable = baReliable;
        }
        String bpReliable = config.getString(configPath + "/bindport[@type='reliable']");
        if (StringUtils.isNotEmpty(bpReliable)) {
            bindPortReliable = new Integer(bpReliable);
        }
        String baFast = config.getString(configPath + "/bindaddress[@type='fast']");
        if (StringUtils.isNotEmpty(baFast)) {
            bindAddressFast = baFast;
        }
        String bpFast = config.getString(configPath + "/bindport[@type='fast']");
        if (StringUtils.isNotEmpty(bpFast)) {
            bindPortFast = new Integer(bpFast);
        }
        String to = config.getString(configPath + "/timeout");
        if (StringUtils.isNotEmpty(to)) {
            timeout = new Integer(to);
        }
        String mPackets = config.getString(configPath + "/maxpackets");
        if (StringUtils.isNotEmpty(mPackets)) {
            maxPackets = new Integer(mPackets);
        }

        if (config.containsKey(configPath + "/messagebroker/@ref")) {
            String messageBrokerRef = config.getString(configPath + "/messagebroker/@ref");
            messageBroker = Jgf.getDirectory().getObjectAs(messageBrokerRef, MessageBroker.class);
            messageBroker.registerMessagePublisher(this);
            int index = 1;
            while (config.containsKey(configPath + "/messagebroker/subscription[" + index + "]/@topic")) {
                String topic = config.getString(configPath + "/messagebroker/subscription[" + index + "]/@topic");
                messageBroker.registerMessageSubscriber(this, topic);
                index++;
            }
        }
    }

    /**
     * @return the bindAddressReliable
     */
    public final String getBindAddressReliable() {
        return bindAddressReliable;
    }

    /**
     * @param bindAddressReliable the bindAddressReliable to set
     */
    public final void setBindAddressReliable(String bindAddressReliable) {
        this.bindAddressReliable = bindAddressReliable;
    }

    /**
     * @return the bindPortReliable
     */
    public final Integer getBindPortReliable() {
        return bindPortReliable;
    }

    /**
     * @param bindPortReliable the bindPortReliable to set
     */
    public final void setBindPortReliable(Integer bindPortReliable) {
        this.bindPortReliable = bindPortReliable;
    }

    /**
     * @return the bindAddressFast
     */
    public final String getBindAddressFast() {
        return bindAddressFast;
    }

    /**
     * @param bindAddressFast the bindAddressFast to set
     */
    public final void setBindAddressFast(String bindAddressFast) {
        this.bindAddressFast = bindAddressFast;
    }

    /**
     * @return the bindPortFast
     */
    public final Integer getBindPortFast() {
        return bindPortFast;
    }

    /**
     * @param bindPortFast the bindPortFast to set
     */
    public final void setBindPortFast(Integer bindPortFast) {
        this.bindPortFast = bindPortFast;
    }

    /**
     * @return the timeout
     */
    public final Integer getTimeout() {
        return timeout;
    }

    /**
     * @param timeout the timeout to set
     */
    public final void setTimeout(Integer timeout) {
        this.timeout = timeout;
    }

    /**
     * @return the maxPackets
     */
    public final Integer getMaxPackets() {
        return maxPackets;
    }

    /**
     * @param maxPackets the maxPackets to set
     */
    public final void setMaxPackets(Integer maxPackets) {
        this.maxPackets = maxPackets;
    }

    @Override
    public void connect() throws IOException {
        JGN.register(JGNChatMessage.class);

        InetSocketAddress reliableAddress = new InetSocketAddress(InetAddress.getByName(bindAddressReliable),
                bindPortReliable);
        InetSocketAddress fastAddress = new InetSocketAddress(InetAddress.getByName(bindAddressFast), bindPortFast);
        server = new JGNServer(reliableAddress, fastAddress);
        //server.addMessageListener(this);
        server.addClientConnectionListener(this);

        JGN.createThread(server).start();
    }

    @Override
    public void disconnect() {
        for (short clientId : clientIds.keySet()) {
            try {
                String playerId = clientIds.get(clientId);
                server.disconnect(clientId);
                clientIds.remove(clientId);
                playerIds.remove(playerId);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            server.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void messageCertified(Message message) {
        // TODO Auto-generated method stub

    }

    @Override
    public void messageFailed(Message message) {
        // TODO Auto-generated method stub

    }

    @Override
    public void messageReceived(Message message) {
        if (message instanceof JGNMessage) {
            JGNMessage jgnMessage = (JGNMessage) message;
            BaseJGFMessage jgfMessage = (BaseJGFMessage) TranslatorMap.translate(jgnMessage);
            // this step needs to be done manually since the playerId in the
            // JGNMessage is used by JGN for other purposes already.
            jgfMessage.setPlayerId(jgnMessage.getPlayerKey());
            System.out.println("message received from " + jgnMessage.getPlayerKey());
            jgfMessage.setTopic(jgfMessage.getMessageCategory() + "_received");
            messageBroker.publishMessage(jgfMessage, this.getId());
        }
    }

    @Override
    public void messageSent(Message message) {
        // TODO Auto-generated method stub

    }

    private void sendMessage(BaseJGFMessage jgfMessage) {
        short clientId = playerIds.get(jgfMessage.getPlayerId());
        // ((JGFChatMessage) jgfMessage).setText("loopback - " +
        // ((JGFChatMessage) jgfMessage).getText());
        JGNMessage jgnMessage = (JGNMessage) TranslatorMap.translate(jgfMessage);
        jgnMessage.setPlayerKey(jgfMessage.getPlayerId());
        server.getConnection(clientId).sendMessage(jgnMessage);
        // messageReceived(jgnMessage);
    }

    @Override
    public void receiveNotification(BaseJGFMessage message, MessageNotifications notification) {
        if (notification == MessageNotifications.NO_SUBSCRIBERS) {
            logger.debug("No subscribers defined");
        }
    }

    @Override
    public void receiveMessage(BaseJGFMessage message) {
        sendMessage(message);
    }

    @Override
    public void connected(JGNConnection connection) {
        System.out.println(connection + " connected on server");
    }

    @Override
    public void disconnected(JGNConnection connection) {
        System.out.println(connection + " disconnected on server");
    }

}

When I call the ClientConnector connect method, I see the client is connected. message, but not the logged in as Player message.

No idea why really.
Logged
Tumaini
JGN Developer
Jr. Member
*****
Offline Offline

Posts: 51


View Profile
« Reply #5 on: November 23, 2009, 03:02:35 PM »

I think I've found a solution.
I'm not sure why yet, but if you create a new JGNClient with no parameters, it seems it doesn't call the connected() method on the client, nor the disconnected() method.
But if you create a new JGNClient with InetSocketAddresses for binding on it works!
Tested in BasicServer and BasicClient:

Code:
JGNClient client = new JGNClient(new InetSocketAddress(InetAddress.getLocalHost(), 0), new InetSocketAddress(InetAddress.getLocalHost(), 0));

Hope that helps!
Logged
ractoc
Newbie
*
Offline Offline

Posts: 8


View Profile
« Reply #6 on: November 23, 2009, 03:37:13 PM »

Ok, I tried this change in the BasicClient, and now the BasicServer does show the line printed in the connected / disconnected methods. However the lines in the connected / disconnected method still don't show up...
Logged
Tumaini
JGN Developer
Jr. Member
*****
Offline Offline

Posts: 51


View Profile
« Reply #7 on: November 24, 2009, 03:26:42 AM »

Do you mean that the connected/disconnected methods aren't called in BasicClient when you do this change?
If so, that's very strange, because I did that change in BasicClient (in the JGN tests) and it the connected/disconnected methods were called in both BasicClient and BasicServer. What IDE are you using?
Logged
ractoc
Newbie
*
Offline Offline

Posts: 8


View Profile
« Reply #8 on: November 24, 2009, 03:34:03 AM »

I'm using eclipse. And in the BasicClient I see the lines in the connected/disconnected methods appear in the console. In the BasicServer console however, the lines in the Connected/disconnected methods do not appear.

I'll try add the change to my own server code later, see if that will fix my problems there. I currently don't really need the connect / disconnect methods besides logging so not that big a deal. As long as the connection IS made, I'm happy (for now anyways).
Logged
ractoc
Newbie
*
Offline Offline

Posts: 8


View Profile
« Reply #9 on: November 25, 2009, 02:35:21 PM »

Ok, I figured out why the BasicClient / BasicServer example wasn't working for me.
I changed
Code:
InetAddress.getByName("127.0.0.1")
to
Code:
InetAddress.getLocalHost()
In all occurences in both the BasicClient and the BasicServer on top of the fix supplied by Tumaini. This fixed things for me, now the connected and disconnected methods are called correctly both on the BasicClient and the BasicServer.
Logged
Tumaini
JGN Developer
Jr. Member
*****
Offline Offline

Posts: 51


View Profile
« Reply #10 on: November 26, 2009, 04:11:52 AM »

Thanks for finding that.
I think it might be related to how InetAddress works on different computers, I've heard it might not be quite perfect.
Logged
ractoc
Newbie
*
Offline Offline

Posts: 8


View Profile
« Reply #11 on: November 26, 2009, 05:22:10 AM »

No problem. If and when I find other issues, with solutions I'll let you know.

On a side note, JGF now has network support.... Although the server side still needs some major work, we are now able to send messages between client and server with JGN.
Logged
darkfrog
Administrator
Inspired Imagination
*****
Offline Offline

Posts: 2650


View Profile
« Reply #12 on: November 28, 2009, 06:43:20 AM »

The getLocalHost() versus getByName("127.0.0.1") is a very different thing.  getLocalHost() *should* get your network IP address and bind to it whereas 127.0.0.1 will only bind to your internal address making it impossible for anything outside to connect to it.  However, that "should" I mentioned before has been a problem I believe primarily on Linux for people as it doesn't always get the right address.  If you search the forums you'll see more discussion and a code solution for it...perhaps it would be beneficial for this to be integrated in JGN at some point?
Logged
ractoc
Newbie
*
Offline Offline

Posts: 8


View Profile
« Reply #13 on: November 28, 2009, 01:46:54 PM »

This is something that should be fixed I think. But for now I have put in a switch on the 127.0.0.1 ip address which uses the getLocalHost when that ip is used.
Not a very clean solution, but for now it works.
When a more clean solution is availlable, I'll be more then happy to switch to that.

How are you guys with code generation via annotation btw.? Been trying to get something to work on that end, but can't figure out how.
Logged
darkfrog
Administrator
Inspired Imagination
*****
Offline Offline

Posts: 2650


View Profile
« Reply #14 on: November 30, 2009, 01:43:30 PM »

Yeah, I agree...Sun simply does a poor job on bug like this.

It's been a long time since I've done much with annotations so I wouldn't be much help.
Logged
Pages: [1]   Go Up
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Page created in 0.277 seconds with 23 queries.