Multiple Clients for one Server (Java)

nerosneros Member Mauris DupondOrganization: CERIProject: middleware
edited February 2018 in Help Center

Could you tell me if its possible to have 3 clients which call methods of a single server ?

Best Answer

  • mesmes CaliforniaMark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff
    Accepted Answer

    Yes, this is possible. Just be aware that the default size for the server-side thread pool is 1, meaning only one request will be dispatched at a time. If you need multiple requests to be dispatched simultaneously, you'll have to increase the maximum size of the server-side thread pool.

«1

Answers

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff
    Accepted Answer

    Yes, this is possible. Just be aware that the default size for the server-side thread pool is 1, meaning only one request will be dispatched at a time. If you need multiple requests to be dispatched simultaneously, you'll have to increase the maximum size of the server-side thread pool.

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware

    " meaning only one request will be dispatched at a time " => Only one client can call server methods at the same time ?

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware
    edited February 2018

    In fact, I need that during a server method calling, an other client call an other server method to set a class attribute (server class) in order to provide the information needed by the return value of the method called by the first client

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff
    edited February 2018

    Only one client can call server methods at the same time ?

    Yes, in the default configuration.

    In fact, I need that during a server method calling, an other client call an other server method to set a class attribute (server class) in order to provide the information needed by the return value of the method called by the first client

    In this case you will need to configure the server-side thread pool in the server to have at least two threads:
    Ice.ThreadPool.Server.Size=2

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware

    Could you tell me where I must set the attribute value ?

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    There are several ways to set configuration properties:

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware
    edited March 2018

    Thanks.

    Consequently, by code I must add

    local interface Properties
    {
    void setProperty("Ice.ThreadPool.Server.Size", "2");

    }
    

    in Slice definition ?

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    Not in your Slice definition, this goes in your server code. For example:

    public static void main(String[] args)
    {
        com.zeroc.Ice.InitializationData initData = new com.zeroc.Ice.InitializationData();
        initData.properties = Ice.Util.createProperties(args);
        initData.properties.setProperty("Ice.ThreadPool.Server.Size", "2");
        com.zeroc.Ice.Communicator communicator = Ice.Util.initialize(initData);
        ...
    }
    
  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware
    edited March 2018
            com.zeroc.Ice.InitializationData initData = new com.zeroc.Ice.InitializationData();
            initData.properties = com.zeroc.Ice.Util.createProperties(args);
            initData.properties.setProperty("Ice.ThreadPool.Server.Size", "2");
    
    
            try(com.zeroc.Ice.Communicator communicator = com.zeroc.Ice.Util.initialize(initData))
            {
    
                com.zeroc.Ice.ObjectAdapter adapter = communicator.createObjectAdapterWithEndpoints("clientmetaserveurAdapter", "default -p 10000");
                com.zeroc.Ice.Object object = new ClientMetaServeurI();
                adapter.add(object, com.zeroc.Ice.Util.stringToIdentity("clientmetaserveur"));
                adapter.activate();
                communicator.waitForShutdown();
            }
    

    is correct ?

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    Yes that looks correct.

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware
    edited March 2018

    In the Java Mapping for struct example :

    public final class Employee implements java.lang.Cloneable, java.io.Serializable
    {
    public long number;
    public String firstName;
    public String lastName;

    public Employee() {}
    
    public Employee(long number, String firstName, String lastName)
    {
        this.number = number;
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    public boolean equals(java.lang.Object rhs)
    {
        // ...
    }
    public int hashCode()
    {
        // ...
    }
    
    public java.lang.Object clone()
    {
        java.lang.Object o;
        try
        {
            o = super.clone();
        }
        catch(java.lang.CloneNotSupportedException ex)
        {
            assert false; // impossible
        }
        return o;
    }
    

    }

    public boolean equals(java.lang.Object rhs) and public int hashCode() must be empty ?

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    Not sure I understand your question. slice2java does generate code for those methods, we just don't show it in the manual. You can run slice2java and then review the generated code if you want.

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware
    edited March 2018

    In fact, I don't need to write myself the java mapping code for struct, it will be automatically generated by slice2java (like String or void types in Slice definition automatically generated...) ?

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    That's correct.

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware
    edited March 2018

    Thanks, could you tell me if com.zeroc.Ice.Current current in parameter of a server method not called by the client (used by server himself) is required ?

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    The Ice run time automatically supplies the Current argument to every servant method. Your servant methods must declare this parameter even if you don't use it.

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware

    An Ice client must be instantiate in a main function, or it can be everywhere... ?

    In fact, One of my ice clients is also an IceStorm Subscriber.

    On Topic message receiving, the client must call an ice server method.

    To do this, I would like to instantiate, use and close an ice client "dynamically" (on some message received contents...)

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    A Communicator represents an instance of the Ice run time. I'm guessing that this is what you mean when you say "ice client". You can create a communicator anywhere, but you also have to ensure the communicator is destroyed. Note that it's not usually necessary for a program to create more than one communicator, and in fact it would be somewhat inefficient to repeatedly create and destroy a communicator every time you needed to make an invocation.

    Take a look at our IceStorm subscriber example. It shows how to implement a subscriber and properly handle the destruction of the communicator.

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware

    In fact, I'm trying to instantiate an IceClient in a Java Class Constructor, its possible... ?

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    We would need to see some code in order to answer that.

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware
    edited March 2018

    Sorry for the delay, I'm very busy with many tasks to do...

    I need that an IceStorm Subscriber send an answer to an Ice Server by creating a temporary Ice Client to call Ice Server methods....

    In order to do that, I think put IceClient in a Java Class and simply crean an object when I need to create a Ice Client to send an answer to Ice Server

    A part of my IceStorm Subscriber code (ClientServeur is the class in which IceClient is coded) :smile:

                          if (m.message.length() > 0) {
                              String[] trame=m.message.split(",");
    
                              if(trame[0].equals("Add")) {
    
                                  if(trame[2].equals("Serveur1")) { this.addMorceau(trame[1], curr); }
    
    
                              } else if(trame[0].equals("Search")) {
    
                                  new ClientServeur(getMorceauByTitre(trame[1], curr));
    
                              } else if(trame[0].equals("Delete")) {
    
                                  this.deleteMorceau(trame[1], curr);
    
                              } else if(trame[0].equals("List")) {
    
                                  new ClientServeur(new String("Serveur1," + this.getListeMorceauxSerialise(curr)));
    
                              } else if(trame[0].equals("Size")) {
    
                                  new ClientServeur(new String("Serveur1," + String.valueOf(this.listeMorceaux.size())));
    
                              } 
    
                          }
    

    ClientServeur class :

    public class ClientServeur {

    public ClientServeur(String message) {
           try(com.zeroc.Ice.Communicator communicator = com.zeroc.Ice.Util.initialize(""))
            {
                com.zeroc.Ice.ObjectPrx base = communicator.stringToProxy("clientmetaserveur:default -p 10000");
                MP3.PrinterPrx printer = MP3.PrinterPrx.checkedCast(base);
                if(printer == null)
                {
                    throw new Error("Invalid proxy");
                }
                printer.setReponse(message);
            }
    
    }
    

    }

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    Yes, you can do that. As I wrote earlier, it's not a very efficient strategy because initializing and destroying communicators is relatively expensive. But if this is something you only do occasionally, and it makes the code simpler, then go ahead. In general though, an application typically initializes a communicator once and uses it throughout the program.

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware
    edited March 2018

    Thanks, Could you tell me if its possible to share the same servant instance for 3 Ice clients ?

    I have a list in servant class attribute and I need to share the list content with the ice clients (clients will remove, add on the same list...)

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    Yes, that is possible and very common. You should familiarize yourself with the Ice threading model, if you haven't already. By default, there is only one thread in the server-side thread pool, which means only one client request will be processed at a time. You can configure the thread pool with more threads, but then you'll need to use synchronization in the servant.

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware
    edited March 2018

    I think that I have a problem.

    In the Ice servant object shared by all Ice clients, a method is blocking until all others client have no answered by calling a method on this servant object...

    while(this.countSubstring("KGmqUPGJpe3DoRteSNPV", this.reponse, current) != this.listeServeurs.size());

    The code is waiting until all client have answered

    Ice can do that... ?

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    If I understand what you're asking, you want a Slice operation to block until the server has received requests from all clients? This is certainly possible, but again it raises threading issues. You'll either need to increase the size of the server-side thread pool so that there are at least as many threads as there are clients, or your servant can use AMD for its implementation.

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware

    I have an error when I run IceStorm Server :

    threadClientMetaServeur (9) : START
    Exception in thread "threadClientMetaServeur" com.zeroc.Ice.ConnectFailedException
    error = 0
    at com.zeroc.IceInternal.OutgoingAsync.waitForResponseOrUserEx(OutgoingAsync.java:146)
    at com.zeroc.IceInternal.OutgoingAsync.waitForResponse(OutgoingAsync.java:118)
    at com.zeroc.Ice._ObjectPrxI.ice_isA(_ObjectPrxI.java:36)
    at com.zeroc.Ice.ObjectPrx._checkedCast(ObjectPrx.java:862)
    at com.zeroc.Ice.ObjectPrx._checkedCast(ObjectPrx.java:824)
    at com.zeroc.IceStorm.TopicManagerPrx.checkedCast(TopicManagerPrx.java:291)
    at Serveur.MetaServeur$1.run(MetaServeur.java:23)
    at java.lang.Thread.run(Thread.java:748)
    Caused by: java.net.ConnectException: Connexion refusée
    at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
    at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717)
    at com.zeroc.IceInternal.Network.doFinishConnect(Network.java:541)
    at com.zeroc.IceInternal.StreamSocket.connect(StreamSocket.java:96)
    at com.zeroc.IceInternal.TcpTransceiver.initialize(TcpTransceiver.java:30)
    at com.zeroc.Ice.ConnectionI.initialize(ConnectionI.java:2095)
    at com.zeroc.Ice.ConnectionI.message(ConnectionI.java:1078)
    at com.zeroc.IceInternal.ThreadPool.run(ThreadPool.java:416)
    at com.zeroc.IceInternal.ThreadPool.access$500(ThreadPool.java:12)
    at com.zeroc.IceInternal.ThreadPool$EventHandlerThread.run(ThreadPool.java:785)
    ... 1 more

    Code :

    public static void main(String[] args) throws Exception
    {

            Runnable clientMetaServeurRunnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " (" + Thread.currentThread().getId() + ") : START");
    
                        com.zeroc.Ice.Communicator communicator = com.zeroc.Ice.Util.initialize(args);
    
                        com.zeroc.Ice.ObjectPrx obj = communicator.stringToProxy("IceStorm/TopicManager:tcp -p 9999");
                        com.zeroc.IceStorm.TopicManagerPrx topicManager = com.zeroc.IceStorm.TopicManagerPrx.checkedCast(obj);
                        com.zeroc.IceStorm.TopicPrx topic = null;
                        while(topic == null)
                        {
                            try
                            {
                                topic = topicManager.retrieve("MP3");
                            }
                            catch(com.zeroc.IceStorm.NoSuchTopic ex)
                            {
                                try
                                {
                                    topic = topicManager.create("MP3");
                                }
                                catch(com.zeroc.IceStorm.TopicExists ex2)
                                {
                                    // Another client created the topic.
                                }
                            }
                        }
    
                        com.zeroc.Ice.ObjectPrx pub = topic.getPublisher().ice_oneway();
                        MP3.CommunicateurPrx monitor = MP3.CommunicateurPrx.uncheckedCast(pub);
    

    Could you help please ?

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    A "connection refused" error usually means the target server (in this case, IceStorm) is not listening on the host and/or port that was specified in the proxy. Common reasons could be IceStorm isn't running, or IceStorm is listening on a different host/port combination, or the client's proxy is incorrect.

  • nerosneros Member Mauris DupondOrganization: CERIProject: middleware

    I must run another thing that IceStorm Publischer during the same time... ?

  • mesmes CaliforniaAdministrators, ZeroC Staff Mark SpruiellOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    The IceStorm server is required. It relays messages between publishers and subscribers.

Sign In or Register to comment.