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