#define GI_INLINE 1 #include #include namespace GLib = gi::repository::GLib; namespace Gio = gi::repository::Gio; const std::string localhost("127.0.0.1"); static GLib::MainLoop loop; // many calls here support GError // so typically will throw here instead // (unless GError output is explicitly requested in call signature) static bool receive(Gio::Socket s, GLib::IOCondition /*cond*/) { guint8 buffer[1024] = { 0, }; Gio::SocketAddress a; int count = gi::expect(s.receive_from(&a, buffer, sizeof(buffer))); if (count > 0) { // let's see where it came from std::string origin("someone"); auto ia = gi::object_cast(a); if (ia) { origin = ia.get_address().to_string(); origin += ":"; origin += std::to_string(ia.get_port()); } std::cout << origin << " said " << (char *)buffer << std::endl; // quit when idle GLib::idle_add([]() { loop.quit(); return GLib::SOURCE_REMOVE_; }); } return true; } Gio::Socket open(bool listen) { auto socket = gi::expect(Gio::Socket::new_(Gio::SocketFamily::IPV4_, Gio::SocketType::DATAGRAM_, Gio::SocketProtocol::DEFAULT_)); auto address = Gio::InetSocketAddress::new_from_string(localhost, 0); socket.bind(address, false); socket.set_blocking(false); if (listen) { // runtime introspection has a hard time here, // but with a bit of extra information, we can keep going GLib::Source source = socket.create_source(GLib::IOCondition::IN_, nullptr); source.set_callback(receive); source.attach(); } return socket; } static void die(const std::string &why) { std::cerr << why << std::endl; exit(2); } int main(int argc, char **argv) { if (argc < 2) die("missing argument"); std::string msg = argv[1]; std::cout << "will send message " << msg << std::endl; auto recv = open(true); auto local = gi::expect(recv.get_local_address()); auto send = open(false); send.send_to(local, (guint8 *)msg.data(), msg.size(), nullptr); loop = GLib::MainLoop::new_(); loop.run(); }