1#include "InetAddress.h" 2#include "Socket.h" 3 4#include <thread> 5 6#include <stdio.h> 7#include <string.h> 8#include <sys/time.h> 9#include <unistd.h> 10 11const int g_port = 3123; 12 13struct Message 14{ 15 int64_t request; 16 int64_t response; 17} __attribute__ ((__packed__)); 18 19static_assert(sizeof(Message) == 16, "Message size should be 16 bytes"); 20 21int64_t now() 22{ 23 struct timeval tv = { 0, 0 }; 24 gettimeofday(&tv, NULL); 25 return tv.tv_sec * int64_t(1000000) + tv.tv_usec; 26} 27 28void runServer(bool ipv6) 29{ 30 Socket sock(Socket::createUDP(ipv6 ? AF_INET6 : AF_INET)); 31 sock.bindOrDie(InetAddress(g_port, ipv6)); 32 33 while (true) 34 { 35 Message message = { 0, 0 }; 36 37 struct sockaddr_storage peerAddr; 38 bzero(&peerAddr, sizeof peerAddr); 39 socklen_t addrLen = sizeof peerAddr; 40 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&peerAddr); 41 42 ssize_t nr = ::recvfrom(sock.fd(), &message, sizeof message, 0, addr, &addrLen); 43 if (nr == sizeof message) 44 { 45 message.response = now(); 46 ssize_t nw = ::sendto(sock.fd(), &message, sizeof message, 0, addr, addrLen); 47 if (nw < 0) 48 { 49 perror("send Message"); 50 } 51 else if (nw != sizeof message) 52 { 53 printf("sent message of %zd bytes, expect %zd bytes.\n", nw, sizeof message); 54 } 55 } 56 else if (nr < 0) 57 { 58 perror("recv Message"); 59 } 60 else 61 { 62 printf("received message of %zd bytes, expect %zd bytes.\n", nr, sizeof message); 63 } 64 } 65} 66 67void runClient(const char* server_hostname) 68{ 69 InetAddress serverAddr; 70 if (!InetAddress::resolve(server_hostname, g_port, &serverAddr)) 71 { 72 printf("Unable to resolve %s\n", server_hostname); 73 return; 74 } 75 76 Socket sock(Socket::createUDP(serverAddr.family())); 77 78 if (sock.connect(serverAddr) != 0) 79 { 80 perror("connect to server"); 81 return; 82 } 83 84 std::thread thr([&sock] () { 85 while (true) 86 { 87 Message message = { 0, 0 }; 88 message.request = now(); 89 int nw = sock.send(&message, sizeof message); 90 if (nw < 0) 91 { 92 perror("send Message"); 93 } 94 else if (nw != sizeof message) 95 { 96 printf("sent message of %d bytes, expect %zd bytes.\n", nw, sizeof message); 97 } 98 99 ::usleep(200*1000); 100 } 101 }); 102 103 while (true) 104 { 105 Message message = { 0, 0 }; 106 int nr = sock.recv(&message, sizeof message); 107 if (nr == sizeof message) 108 { 109 int64_t back = now(); 110 int64_t mine = (back + message.request) / 2; 111 printf("now %jd, round trip time %jd us, clock error %jd us\n", 112 back, back - message.request, message.response - mine); 113 } 114 else if (nr < 0) 115 { 116 perror("recv Message"); 117 } 118 else 119 { 120 printf("received message of %d bytes, expect %zd bytes.\n", nr, sizeof message); 121 } 122 } 123} 124 125int main(int argc, const char* argv[]) 126{ 127 if (argc < 2) 128 { 129 printf("Usage:\nServer: %s -s [-6]\nClient: %s server_hostname\n", argv[0], argv[0]); 130 return 0; 131 } 132 133 if (strcmp(argv[1], "-s") == 0) 134 { 135 bool ipv6 = argc > 2 ? strcmp(argv[2], "-6") == 0 : false; 136 runServer(ipv6); 137 } 138 else 139 { 140 runClient(argv[1]); 141 } 142} 143