Search code examples
javasocketsgroovyclient-serverunetstack

Creating a communication between client and server node in unetstack using UnetSocket


I am new to this domain of UnetStack and would appreciate help from the experts.

I have created a small network of 4 nodes. I am trying to connect my client node, e.g. node B, to the server node (A). I tried the communication between them through the shell. I was successful in it. But I am facing errors when I tried the same through agents. Basically, my client agent holds socket code for the client and the same case is for my server. My aim is to make fully functional communication between client and server nodes.

I created a server agent, and the client agent added those agents to the respective stacks of nodes. In the above-mentioned agents, I tried to implement my server socket code and client socket code in the respective agent's .groovy file. The server agent is added in the setup file named setup1.groovy while the Client agent is added in the setup2.groovy. The path to these respective files is mentioned in the respective node's stack section in the simulation script. But still, I am facing the following error:

SEVERE: Client/B > Agent cli died: groovy.lang.MissingMethodException: No signature of method: org.arl.unet.api.UnetSocket.connect() is applicable for argument types: (String, Integer) values: [1, 0]
Possible solutions: connect(int, int), collect(), disconnect(), cancel(), collect(groovy.lang.Closure), collect(java.util.Collection, groovy.lang.Closure)

I am attaching my simulation and agent script for more insight.

Server agent file(server.groovy)

import org.arl.fjage.*
import org.arl.unet.*
import java.lang.String
//import org.arl.fjage.Agent
import org.arl.unet.api.UnetSocket
class server extends UnetAgent {
  @Override
  void startup() {
    def sock = new UnetSocket('localhost',1105)
    println('Server is active now!!!!!')
    sock.bind(Protocol.DATA)
    def rx= sock.receive()
    println(rx.from,rx.to,rx.data)
    sock.close()
  }  
}

Client agent file(client.groovy)

import org.arl.fjage.*
import org.arl.unet.*
import java.lang.String
import org.arl.fjage.Agent
import org.arl.unet.api.UnetSocket
class Client extends UnetAgent {
  @Override
  void startup() {
    add new WakerBehavior(5000,{
      def sock= new UnetSocket('localhost',1102)
      //def to = sock.host('A') 
      println('Client Created!!!!!!')
      sock.connect('1', Protocol.DATA) 
      sock.send('Connected!!!' as byte[]) 
      sock.send('Successfully' as byte[]) 
      sock.close()
    })
  } 
}

Simulation Script

import org.arl.fjage.*
//import org.arl.unet.*
///////////////////////////////////////////////////////////////////////////////
// display documentation

println '''
my-node network
--------------

Node A: tcp://localhost:1105, http://localhost:8081/
Node B: tcp://localhost:1102, http://localhost:8082/
Node C: tcp://localhost:1103, http://localhost:8083/
Node D: tcp://localhost:1104, http://localhost:8084/
'''

///////////////////////////////////////////////////////////////////////////////
// simulator configuration

platform = RealTimePlatform   // use real-time mode

// run the simulation forever
simulate {
  node 'A', address:1, location: [ 0.km, 0.km, -15.m], web: 8081, api: 1105, stack: "$home/etc/setup1"
  node 'B', address:2, location: [ -1.km, 1.7.km, -15.m], web: 8082, api: 1102, stack:"$home/etc/setup2"
  node 'C', address:3, location: [ 0.8.km, -1.km, -15.m], web: 8083, api: 1103, stack: "$home/etc/setup"
  node 'D', address:4, location: [ 1.5.km, 1.7.km, -15.m], web: 8084, api: 1104, stack: "$home/etc/setup"
  
  
}

setup1(Server side setup file) setup1.groovy

import org.arl.fjage.Agent
import java.lang.String

boolean loadAgentByClass(String name, String clazz) {
  try {
    container.add name, Class.forName(clazz).newInstance()
    return true
  } catch (Exception ex) {
    return false
  }
}

boolean loadAgentByClass(String name, String... clazzes) {
  for (String clazz: clazzes) {
    if (loadAgentByClass(name, clazz)) return true
  }
  return false
}

loadAgentByClass 'arp',          'org.arl.unet.addr.AddressResolution'
loadAgentByClass 'ranging',      'org.arl.unet.localization.Ranging'
loadAgentByClass 'mac',          'org.arl.unet.mac.CSMA'
loadAgentByClass 'uwlink',       'org.arl.unet.link.ECLink', 'org.arl.unet.link.ReliableLink'
loadAgentByClass 'transport',    'org.arl.unet.transport.SWTransport'
loadAgentByClass 'router',       'org.arl.unet.net.Router'
loadAgentByClass 'rdp',          'org.arl.unet.net.RouteDiscoveryProtocol'
loadAgentByClass 'statemanager', 'org.arl.unet.state.StateManager'

container.add 'serv', new server()
container.add 'remote', new org.arl.unet.remote.RemoteControl(cwd: new File(home, 'scripts'), enable: false)
container.add 'bbmon',  new org.arl.unet.bb.BasebandSignalMonitor(new File(home, 'logs/signals-0.txt').path, 64)

Setup2.groovy file follows the same format, but the agent added in that case is the client.

Thank you. Regards,


Solution

  • The important part of the error you are seeing is

    No signature of method: org.arl.unet.api.UnetSocket.connect() is applicable for argument types: (String, Integer) values: [1, 0]
    Possible solutions: connect(int, int),
    

    In other words, the connect method you are calling on the UnetSocket with the first argument of type String and the second argument of type int. However, no such method exists, hence the "No signature of method" error.

    In fact compiler hints at other possible methods that might be helpful including one which takes in int as both arguments, which is the one you should be using.

    So changing your client code should help solve this problem.

    void startup() {
        add new WakerBehavior(5000,{
          def sock= new UnetSocket('localhost',1102)
          //def to = sock.host('A') 
          println('Client Created!!!!!!')
          sock.connect(1, Protocol.DATA) 
          sock.send('Connected!!!' as byte[]) 
          sock.send('Successfully' as byte[]) 
          sock.close()
        })
      } 
    

    Do note though that you are creating a new socket inside a WakerBehaviour, so you'll be creating new Sockets every 5 seconds. You might not want to do that.