Although multicasting is a better solution, sometimes multicasting is not possible with certain architectures; hence UDPPoset.
The advantage of UDPPoset over a vector of UDP sockets is that each instantiation of a UDP socket will use a local port. In contrast, the UDPPoset class will use a single port for all outgoing UDP traffic. Like the UDP class it inherits from, it is capable of receiving transmissions, but only for the single local port.
UDPPoset will only accept UDP unicast addresses; not multicast; not broadcast.
The name poset, or partially ordered set, was used since UDP destinations of equal priority have no guarantees on ordering. Priority is a numeric value, and transmissions will occur from the highest priority first to the lowest priority last.
/*************************************************************************** * Copyright (C) 2001 by Rick L. Vinyard, Jr. * * rvinyard@cs.nmsu.edu * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation version 2.1. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ #include <conexus/conexus.h> #include <iostream> int main(int argc, char* argv[]) { Conexus::init(); // declare the local UDP connection point Conexus::IPv4::UDPPoset udp; // declare the address object that will be used to specify the destination Conexus::IPv4::Address addr1, addr2, addr3; // The data to send char data[] = "0123456789"; // Some default values for host and port char defaulthost[] = "127.0.0.1"; char* host = defaulthost; int port1 = 1500, port2=1501, port3=1502; // Check to see if user provided command line arguments and change // host and port variables if necessary if (argc > 1) host = argv[1]; if (argc > 2) port1 = atoi(argv[2]); if (argc > 3) port2 = atoi(argv[3]); if (argc > 4) port3 = atoi(argv[4]); // Set the address object to the destination hostname and port addr1.set_address(host); addr1.set_port(port1); addr2.set_address(host); addr2.set_port(port2); addr3.set_address(host); addr3.set_port(port3); // Example of using the connect and send method. The send method doesn't // require an address, but instead requires a connected UDP object and // just sends to the connected destination. udp.add_destination(addr1, 0); udp.add_destination(addr2, 1); udp.add_destination(addr3, -1); udp.write(data, 11); return 0; }
/*************************************************************************** * Copyright (C) 2001 by Rick L. Vinyard, Jr. * * rvinyard@cs.nmsu.edu * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation version 2.1. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ #include <conexus/conexus.h> #include <sys/types.h> #include <unistd.h> #include <iostream> // prototypes of the three print callback functions void print_data1(Conexus::Data d); void print_data2(Conexus::Data d); void print_data3(Conexus::Data d); int main() { // Initialize the Conexus library // This is needed because we will use threaded servers and this // will do all the behind the scenes work to initialize pthreads Conexus::init(); // Declare the udp object Conexus::IPv4::UDP udp1, udp2, udp3; // Set the port udp1.local_interface().set_port(1500); udp2.local_interface().set_port(1501); udp3.local_interface().set_port(1502); // The server connect method connects a provided sigc++ slot that will be called // back when the server receives any data. udp1.signal_data().connect(sigc::ptr_fun(&print_data1)); udp2.signal_data().connect(sigc::ptr_fun(&print_data2)); udp3.signal_data().connect(sigc::ptr_fun(&print_data3)); // Start the server. The server will spawn a separate thread to service // received data, so this call will immediately return after the thread // is spawned. udp1.start(); udp2.start(); udp3.start(); std::cout << "Main thread pid: " << pthread_self() << std::endl; // Set up a loop that will run for 20 seconds and print the time every 5 // seconds. Since the server is threaded, the sleep(1) call will not effect // the servicing thread. std::cout << "Starting..." << std::endl; for (int i=1; i <= 20; i++) { if (i%5 == 0) std::cout << "Time: " << i << std::endl; sleep(1); } // Stop the server and prepare for shutdown udp1.stop(); udp2.stop(); udp3.stop(); return 0; } // These are the three callback functions. Each simply prints out the data received. void print_data1(Conexus::Data d) { std::cout << "Responding thread pid: " << pthread_self() << std::endl; std::cout << "<1> Received " << d.size() << " bytes of data [" << d << "]\n"; } void print_data2(Conexus::Data d) { std::cout << "Responding thread pid: " << pthread_self() << std::endl; std::cout << "<2> Received " << d.size() << " bytes of data [" << d << "]\n"; } void print_data3(Conexus::Data d) { std::cout << "Responding thread pid: " << pthread_self() << std::endl; std::cout << "<3> Received " << d.size() << " bytes of data [" << d << "]\n"; }