chiark / gitweb /
UDP listen/send utils
authorRichard Kettlewell <rjk@greenend.org.uk>
Thu, 16 Dec 2010 22:50:17 +0000 (22:50 +0000)
committerRichard Kettlewell <rjk@greenend.org.uk>
Thu, 16 Dec 2010 22:50:17 +0000 (22:50 +0000)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
udplisten.cc [new file with mode: 0644]
udpsend.cc [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..cacd675
--- /dev/null
@@ -0,0 +1,4 @@
+udplisten
+udpsend
+*.o
+*~
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..ee79821
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+CXX=c++ -Wall -W
+
+all: udplisten udpsend
+
+udplisten: udplisten.o
+       $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) $<
+
+udpsend: udpsend.o
+       $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) $<
+
+clean:
+       rm -f *.o
+       rm -f udpsend udplisten
diff --git a/udplisten.cc b/udplisten.cc
new file mode 100644 (file)
index 0000000..6685bf5
--- /dev/null
@@ -0,0 +1,65 @@
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <cerrno>
+#include <cstdarg>
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+
+static int portno = 4096;
+
+static void fatal(const char *s, ...) {
+  int e = errno;
+  va_list ap;
+  va_start(ap, s);
+  vfprintf(stderr, s, ap);
+  va_end(ap);
+  fprintf(stderr, " (errno=%s)\n", strerror(e));
+  exit(1);
+}
+
+int bindto(const char *dev) {
+  struct sockaddr_in addr;
+  int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+  if(fd < 0) fatal("socket");
+  const int one = 1;
+  if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) < 0)
+    fatal("setsockopt SO_REUSEADDR");
+  if(dev && *dev) {
+    if(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, dev, strlen(dev)) < 0)
+      fatal("setsockopt SO_BINDTODEVICE %s", dev);
+  }
+  memset(&addr, 0, sizeof addr);
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons(portno);
+  addr.sin_addr.s_addr = 0;
+  if(bind(fd, (struct sockaddr *)&addr, sizeof addr) < 0)
+    fatal("bind");
+  return fd;
+}
+
+int main(int argc, char **argv) {
+  char buffer[4096];
+  int fds[64];
+  for(int n = 1; n < argc; ++n)
+    fds[n] = bindto(argv[n]);
+  for(;;) {
+    fd_set fdset;
+    FD_ZERO(&fdset);
+    for(int n = 1; n < argc; ++n)
+      FD_SET(fds[n], &fdset);
+    int rc = select(fds[argc-1] + 1, &fdset, NULL, NULL, NULL);
+    if(rc < 0)
+      fatal("select");
+    for(int n = 1; n < argc; ++n) {
+      if(FD_ISSET(fds[n], &fdset)) {
+        int len = read(fds[n], buffer, sizeof buffer - 1);
+        if(len < 0)
+          fatal("recv (%s)", argv[n]);
+        buffer[len] = 0;
+        printf("%s: %s\n", argv[0], buffer);
+      }
+    }
+  }
+}
diff --git a/udpsend.cc b/udpsend.cc
new file mode 100644 (file)
index 0000000..cd36181
--- /dev/null
@@ -0,0 +1,41 @@
+#include <cerrno>
+#include <cstdarg>
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+static void fatal(const char *s, ...) {
+  int e = errno;
+  va_list ap;
+  va_start(ap, s);
+  vfprintf(stderr, s, ap);
+  va_end(ap);
+  fprintf(stderr, " (errno=%s)\n", strerror(e));
+  exit(1);
+}
+
+int main(int argc, char **argv) {
+  if(argc != 4)
+    fatal("usage: udpsend HOST PORT MESSAGE");
+  struct addrinfo hints, *res;
+  memset(&hints, 0, sizeof hints);
+  hints.ai_family = AF_UNSPEC;
+  hints.ai_socktype = SOCK_DGRAM;
+  hints.ai_protocol = IPPROTO_UDP;
+  hints.ai_flags = 0;
+  int rc = getaddrinfo(argv[1], argv[2], &hints, &res);
+  if(rc)
+    fatal("getaddrinfo: %s", gai_strerror(rc));
+  int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+  if(fd < 0)
+    fatal("socket");
+  if(connect(fd, res->ai_addr, res->ai_addrlen) < 0)
+    fatal("connect");
+  if(write(fd, argv[3], strlen(argv[3]) + 1) < 0)
+    fatal("write");
+  return 0;
+}