Here's an example of opening and reading data from a TCP socket. Is there a way to create a UDP socket as well?
void setup() {
c = new Client(this, "127.0.0.1", 12345); // Replace with your server's IP and port
}
void draw() {
if (c.available() > 0) {
input = c.readString();
http://www.processing.org/learning/libraries/sharedcanvasclient.html
You can use the UDP library for processing (http://ubaa.net/shared/processing/udp/). Some examples are provided, so you can start experimenting with UDP easily.
I have used UDP communication in processing a lot for many projects. The implementation is really good and ready for real world applications.
Related
I am building service that needs to send events to all subscribed consumers in Pub/Sub manner eg. send one event to all currently connected clients.
I am using Protobuf for that with the following proto definition:
service EventsService {
rpc ListenForEvents (AgentProcess) returns (stream Event) {}
}
Both server & client are written in Go.
My problem is that when client initiates connection then the stream it is not long-lived, eg. when server returns from ListenForEvents method:
func (e EventsService) ListenForEvents(process *pb.AgentProcess, listener pb.EventsService_ListenForEventsServer) error {
//persist listener here so it can be used later when backend needs to send some messages to client
return nil
}
then the client almost instantly gets EOF error which means that server probably closed connection.
What do I do so that the client is subscribed for a long time to the server? The main problem is that I might not have anything to send to the client when it calls ListenForEvents method on the server, this is why I want this stream to be long lived to be able to send messages later.
The stream terminates when you return from the server function. Instead, you should receive events somehow, and send them to the client without returning from your server. There are probably many ways you can do this. Below is the sketch of one way of doing it.
This relies on the server connection running on a separate goroutine. There is a Broadcast() function that will send messages to all connected clients. It looks like this:
var allRegisteredClients map[*pb.AgentProcess]chan Message
var clientsLock sync.RWMutex{}
func Broadcast(msg Message) {
clientsLock.RLock()
for _,x:=range allRegisteredClients {
x<-msg
}
clientsLock.RUnlock()
}
Then, your clients have to register themselves, and process messages:
func (e EventsService) ListenForEvents(process *pb.AgentProcess, listener pb.EventsService_ListenForEventsServer) error {
clientsLock.Lock()
ch:=make(chan Message)
allRegisteredClients[process]=ch
clientsLock.Unlock()
for msg:=range ch {
// send message
// Deal with errors
// Deal with client terminations
}
clientsLock.Lock()
delete(allRegisteredClients,process)
clientsLock.Unlock()
}
As I said, this is only a sketch of the idea.
I have managed to nail it down.
Basically I never return from method ListenForEvents.
It creates channel, persists in global-like map of subscribed clients and keeps reading from that channel indefinitely.
The whole implementation of server logic:
func (e EventsService) ListenForEvents(process *pb.AgentProcess, listener pb.EventsService_ListenForEventsServer) error {
chans, exists := e.listeners[process.Hostname]
chanForThisClient := make(chan *pb.Event)
if !exists {
e.listeners[process.Hostname] = []chan *pb.Event{chanForThisClient}
} else {
e.listeners[process.Hostname] = append(chans, chanForThisClient)
}
for {
select {
case <-listener.Context().Done():
return nil
case res := <-chanForThisClient:
_ = listener.Send(res)
}
}
return nil
}
You need to provide keepalive settings for grpc client and server
See details here https://github.com/grpc/grpc/blob/master/doc/keepalive.md
Examples https://github.com/grpc/grpc-go/tree/master/examples/features/keepalive
Iam trying to create simple wireless node for MANET network which can send messages to other nodes in range. Solutions implemented in INET also contains other layers like IP, transport, application which i dont need.
Iam new to omnet++ so iam struggling a bit. I was thinking of creating whole own node with RadioIn input, but i dont know how to implement only in range communication and i will also need node mobility.
Other solutions would be to use only Radiomedium from INET framework but i dont know how to do it.
Can someone please give me some begginer tips how to achieve my goal? As i said i simply need to create mobile host which can send a defined message to all other hosts in range.
EDIT: I tried to take IdealRadioMedium and create my simple module and connect to it. Here is the NED File.
import inet.physicallayer.common.packetlevel.Radio;
import inet.common.figures.DelegateSignalConfigurator;
import inet.networklayer.configurator.ipv4.IPv4NetworkConfigurator;
import inet.node.inet.INetworkNode;
import inet.node.inet.WirelessHost;
import inet.physicallayer.contract.packetlevel.IRadioMedium;
import inet.visualizer.integrated.IntegratedCanvasVisualizer;
import inet.linklayer.contract.IWirelessNic;
import inet.networklayer.common.InterfaceTable;
simple Txc1
{
gates:
input in;
output out;
}
module Pokusny
{
parameters:
#display("i=device/wifilaptop");
int numRadios = default(1);
#networkNode;
gates:
input radioIn[numRadios] #directIn;
submodules:
mynode: Txc1;
wlan[numRadios]: <default("Ieee80211Nic")> like IWirelessNic {
parameters:
#display("p=216,406,row,60;q=queue");
}
interfaceTable: InterfaceTable {
parameters:
#display("p=53,300;is=s");
}
connections allowunconnected:
for i=0..sizeof(radioIn)-1 {
radioIn[i] --> { #display("m=s"); } --> wlan[i].radioIn;
wlan[i].upperLayerOut --> mynode.in;
wlan[i].upperLayerIn <-- mynode.out;
}
}
network WirelessC
{
parameters:
string hostType = default("WirelessHost");
string mediumType = default("IdealRadioMedium");
#display("bgb=650,500;bgg=100,1,grey95");
#figure[title](type=label; pos=0,-1; anchor=sw; color=darkblue);
#figure[rcvdPkText](type=indicatorText; pos=420,20; anchor=w; font=,20; textFormat="packets received: %g"; initialValue=0);
#statistic[rcvdPk](source=hostB_rcvdPk; record=figure(count); targetFigure=rcvdPkText);
#signal[hostB_rcvdPk];
#delegatesignal[rcvdPk](source=hostB.udpApp[0].rcvdPk; target=hostB_rcvdPk);
submodules:
visualizer: IntegratedCanvasVisualizer {
#display("p=580,125");
}
configurator: IPv4NetworkConfigurator {
#display("p=580,200");
}
radioMedium: <mediumType> like IRadioMedium {
#display("p=580,275");
}
//figureHelper: DelegateSignalConfigurator {
// #display("p=580,350");
//}
hostA: Pokusny {
#display("p=50,325");
}
hostB: Pokusny {
#display("p=450,325");
}
}
Txc1.cc
class Txc1 : public cSimpleModule
{
protected:
// The following redefined virtual function holds the algorithm.
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
// The module class needs to be registered with OMNeT++
Define_Module(Txc1);
void Txc1::initialize()
{
cMessage *msg = new cMessage("tictocMsg");
send(msg, "out");
}
void Txc1::handleMessage(cMessage *msg)
{
send(msg, "out"); // send out the message
}
And .ini file
network = WirelessC
sim-time-limit = 25s
*.host*.wlan[0].typename = "IdealWirelessNic"
*.host*.wlan[0].mac.useAck = false
*.host*.wlan[0].mac.fullDuplex = false
*.host*.wlan[0].radio.transmitter.communicationRange = 500m
*.host*.wlan[0].radio.receiver.ignoreInterference = true
*.host*.**.bitrate = 1Mbps
When i run the simulation it asks for Interfacetable parameter which i dont know what to type there becuse i havent found it in traversing functioning code ( I had to add it because it throws error that is missing if its not as submodule). Now iam getting
getCointainingNode() node module not found it should have a property name networkNode for module WirelessC.interfaceTable in module .... durint network initialization
EDIT: I added networknode as parameter and now i got Module not found on path '.mobility' defined by par WirelessC.hostA.wlan[0].radio.antenna.Mobilitymodule in module inte::physicallayer:IsotropicAntenna during network initialization
I'd like to point you to the wireless tutorial for INET: https://omnetpp.org/doc/inet/api-current/tutorials/wireless/
It starts with exactly your problem. The only thing left, is to replace the standard UDP host with a host using no protocol at all, maybe even implementing your own. The whole wireless part is explained in the tutorial.
If you want to check the source files for the used modules you need to walk down the chain of dependency since every compound NED module will (at one point) contain simple modules implemented in C++.
E.g. the module which is responsible for distributing the signals is IdealRadioMedium using RadioMedium. Now you need to find the Node implementation directly communicating with this module.
Starting with the WirelessHost used in the tutorial the underlying modules are
StandardHost -> ApplicationLayerNodeBase -> LinkLayerNodeBase with the later being the first one using actually implemented submodules.
The network adapter used is configured in the omnet.ini with *.host*.wlan[0].typename = "IdealWirelessNic". This module relies on Radio.
With all that found out you just need to look for API calls from Radio.cc made to RadioMedium.cc and you found the actual code responsible for sending data.
Understanding that chain of inheritance you can even hook in with your custom module at a level you find fitting. For example just implementing your own LinklayerNodeBase module.
If you are going for wireless communication and mobility, INET will still be the best framework to use.
Check out the INET Wireless Tutorial. It basically covers all the steps that you need to build a small scenario with moving nodes that communicate wirelessly.
I am trying to use AODV in a wired simulation but I can't make it work, is it possible to link 2 AODVRouters by wire and use the AODV protocol?? or should I use 2 standardhost and modify the AODVrouting.cc??
EDIT:
I just simulate the AODV simpleRREQ example using standardhosts instead of AODVrouters and using the debug mode it crashes in this piece of code:
void AODVRouting::sendAODVPacket(AODVControlPacket *packet, const L3Address& destAddr, unsigned int timeToLive, double delay)
{INetworkProtocolControlInfo *networkProtocolControlInfo = addressType->createNetworkProtocolControlInfo();
networkProtocolControlInfo->setHopLimit(timeToLive);
networkProtocolControlInfo->setTransportProtocol(IP_PROT_MANET);
networkProtocolControlInfo->setDestinationAddress(destAddr);
networkProtocolControlInfo->setSourceAddress(getSelfIPAddress());
// TODO: Implement: support for multiple interfaces
InterfaceEntry *ifEntry = interfaceTable->getInterfaceByName("AODV");
networkProtocolControlInfo->setInterfaceId(ifEntry->getInterfaceId());
UDPPacket *udpPacket = new UDPPacket(packet->getName());
udpPacket->encapsulate(packet);
udpPacket->setSourcePort(aodvUDPPort);
udpPacket->setDestinationPort(aodvUDPPort);
udpPacket->setControlInfo(dynamic_cast<cObject *>(networkProtocolControlInfo));
if (destAddr.isBroadcast())
lastBroadcastTime = simTime();
if (delay == 0)
send(udpPacket, "ipOut");
else
sendDelayed(udpPacket, delay, "ipOut");
}
How can I send the AODV packet throw all the ethernet ports of the router?
I'm beginner with boost::asio and udp networking system.
I'm trying to receive many of packet from multicast(239.255.255.251:5353) and I want to send packet multicast(239.255.255.251:5353) for specific device.
I referenced this example from boost
http://www.boost.org/doc/libs/1_37_0/doc/html/boost_asio/example/multicast/receiver.cpp
and I modified that
void handle_receive_from(const boost::system::error_code& error,
size_t bytes_recvd)
{
if (!error)
{
if(mdns_validate_name(data_, bytes_recvd))
{
std::cout.write(data_, bytes_recvd);
std::cout << std::endl;
/** make packet for send **/
socket_.async_send_to(
boost::asio::buffer(data_, length), multi_endpoint_,
boost::bind(&receiver::handle_send, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
socket_.async_receive_from(
boost::asio::buffer(data_, max_length), multi_endpoint_,
boost::bind(&receiver::handle_receive_from, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
}
}
my problem is packet not over multicast(239.255.255.251:5353). it just sent specific ip(192.168.0.168). I checked wire shark.
I want to send packet again over multicast (239.255.255.251:5353).
please comment!
Unfortunately UDP multicast sending and receiving are completely different.
A receiver uses a local address to select the receiving device: usually set to any. Whilst a sender requires a remote address, i.e. the multicast address. In your case that would be 239.255.255.251.
E.g. from the boost::asio sender example:
class sender
{
public:
sender(boost::asio::io_service& io_service,
const boost::asio::ip::address& multicast_address)
: endpoint_(multicast_address, multicast_port),
socket_(io_service, endpoint_.protocol())
{}
.
.
.
private:
boost::asio::ip::udp::endpoint endpoint_;
boost::asio::ip::udp::socket socket_;
};
BTW the boost::asio UDP example that you reference is very old and for a receiver!
The latest boost::asio UDP sender example is here. However, for your purposes the echo server would be a better starting point.
If you want to see complete example of IPv4 and IPv6 UDP asio comms then have a look at udp_adaptor.hpp here.
I am trying to make a simple server thread in QT to accept a connection, however although the server is listening (I can connect with my test app) I can't get the newConnection() signal to be acted on.
Any help as to what I'm missing here would be much appreciated!
class CServerThread : public QThread
{
Q_OBJECT
protected:
void run();
private:
QTcpServer* server;
public slots:
void AcceptConnection();
};
void CServerThread::run()
{
server = new QTcpServer;
QObject::connect(server, SIGNAL(newConnection()), this, SLOT(AcceptConnection()));
server->listen(QHostAddress::Any, 1000); // Any port in a storm
exec(); // Start event loop
}
void CServerThread::AcceptConnection()
{
OutputDebugStringA("\n***** INCOMING CONNECTION"); // This is never called!
}
First of all I can say that your server lives in new thread while CServerThread instance lives in another thread (in the thread this instance was created). Signal/slot connection you are creating is inderect and uses thread save event delivery between events loops of two different threads. It actually can cause such problem if thread where you creating CServerThread doesn't have Qt event loop running.
I suggest you to create some MyServer class which creates QTcpServer and calls listen and connects QTcpServer::newConnection() signal to its own slot. Then rewrite your server thread run method to something like this:
void CServerThread::run() {
server = new MyServer(host,port);
exec(); // Start event loop
}
In this approach both QTcpServer and newConnection processing object lives in the same thread. Such situation is easier to handle.
I have one really simple working example:
Header: http://qremotesignal.googlecode.com/svn/tags/1.0.0/doc/html/hello_2server_2server_8h-example.html
Source: http://qremotesignal.googlecode.com/svn/tags/1.0.0/doc/html/hello_2server_2server_8cpp-example.html