roundtrip_udp.cc revision 8bdf4aaf
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 28aafef3ccSShuo Chenvoid runServer() 29aafef3ccSShuo Chen{ 3024ca08a8SShuo Chen Socket sock(Socket::createUDP(/*ipv6=*/true)); 31aafef3ccSShuo Chen sock.bindOrDie(InetAddress(g_port)); 32aafef3ccSShuo Chen 33aafef3ccSShuo Chen while (true) 34aafef3ccSShuo Chen { 35aafef3ccSShuo Chen Message message = { 0, 0 }; 36aafef3ccSShuo Chen 37aafef3ccSShuo Chen struct sockaddr peerAddr; 38aafef3ccSShuo Chen bzero(&peerAddr, sizeof peerAddr); 39aafef3ccSShuo Chen socklen_t addrLen = sizeof peerAddr; 40aafef3ccSShuo Chen ssize_t nr = ::recvfrom(sock.fd(), &message, sizeof message, 0, &peerAddr, &addrLen); 41aafef3ccSShuo Chen if (nr == sizeof message) 42aafef3ccSShuo Chen { 43aafef3ccSShuo Chen message.response = now(); 44aafef3ccSShuo Chen ssize_t nw = ::sendto(sock.fd(), &message, sizeof message, 0, &peerAddr, addrLen); 45aafef3ccSShuo Chen if (nw < 0) 46aafef3ccSShuo Chen { 47aafef3ccSShuo Chen perror("send Message"); 48aafef3ccSShuo Chen } 49aafef3ccSShuo Chen else if (nw != sizeof message) 50aafef3ccSShuo Chen { 51aafef3ccSShuo Chen printf("sent message of %zd bytes, expect %zd bytes.\n", nw, sizeof message); 52aafef3ccSShuo Chen } 53aafef3ccSShuo Chen } 54aafef3ccSShuo Chen else if (nr < 0) 55aafef3ccSShuo Chen { 56aafef3ccSShuo Chen perror("recv Message"); 57aafef3ccSShuo Chen } 58aafef3ccSShuo Chen else 59aafef3ccSShuo Chen { 60aafef3ccSShuo Chen printf("received message of %zd bytes, expect %zd bytes.\n", nr, sizeof message); 61aafef3ccSShuo Chen } 62aafef3ccSShuo Chen } 63aafef3ccSShuo Chen} 64aafef3ccSShuo Chen 65aafef3ccSShuo Chenvoid runClient(const char* server_hostname) 66aafef3ccSShuo Chen{ 6724ca08a8SShuo Chen InetAddress serverAddr; 6824ca08a8SShuo Chen if (!InetAddress::resolve(server_hostname, g_port, &serverAddr)) 69f41285cfSShuo Chen { 70f41285cfSShuo Chen printf("Unable to resolve %s\n", server_hostname); 71f41285cfSShuo Chen return; 72f41285cfSShuo Chen } 73f41285cfSShuo Chen 7424ca08a8SShuo Chen Socket sock(Socket::createUDP(serverAddr.family())); 7524ca08a8SShuo Chen 76f41285cfSShuo Chen if (sock.connect(serverAddr) != 0) 77aafef3ccSShuo Chen { 78aafef3ccSShuo Chen perror("connect to server"); 79aafef3ccSShuo Chen return; 80aafef3ccSShuo Chen } 81aafef3ccSShuo Chen 82aafef3ccSShuo Chen std::thread thr([&sock] () { 83aafef3ccSShuo Chen while (true) 84aafef3ccSShuo Chen { 85aafef3ccSShuo Chen Message message = { 0, 0 }; 86aafef3ccSShuo Chen message.request = now(); 878bdf4aafSShuo Chen int nw = sock.send(&message, sizeof message); 88aafef3ccSShuo Chen if (nw < 0) 89aafef3ccSShuo Chen { 90aafef3ccSShuo Chen perror("send Message"); 91aafef3ccSShuo Chen } 92aafef3ccSShuo Chen else if (nw != sizeof message) 93aafef3ccSShuo Chen { 94aafef3ccSShuo Chen printf("sent message of %d bytes, expect %zd bytes.\n", nw, sizeof message); 95aafef3ccSShuo Chen } 96aafef3ccSShuo Chen 97aafef3ccSShuo Chen ::usleep(200*1000); 98aafef3ccSShuo Chen } 99aafef3ccSShuo Chen }); 100aafef3ccSShuo Chen 101aafef3ccSShuo Chen while (true) 102aafef3ccSShuo Chen { 103aafef3ccSShuo Chen Message message = { 0, 0 }; 1048bdf4aafSShuo Chen int nr = sock.recv(&message, sizeof message); 105aafef3ccSShuo Chen if (nr == sizeof message) 106aafef3ccSShuo Chen { 107aafef3ccSShuo Chen int64_t back = now(); 108aafef3ccSShuo Chen int64_t mine = (back + message.request) / 2; 109f41285cfSShuo Chen printf("now %jd round trip %jd clock error %jd\n", 110f41285cfSShuo Chen back, back - message.request, message.response - mine); 111aafef3ccSShuo Chen } 112aafef3ccSShuo Chen else if (nr < 0) 113aafef3ccSShuo Chen { 1148bdf4aafSShuo Chen perror("recv Message"); 115aafef3ccSShuo Chen } 116f41285cfSShuo Chen else 117aafef3ccSShuo Chen { 118aafef3ccSShuo Chen printf("received message of %d bytes, expect %zd bytes.\n", nr, sizeof message); 119aafef3ccSShuo Chen } 120aafef3ccSShuo Chen } 121aafef3ccSShuo Chen} 122aafef3ccSShuo Chen 123aafef3ccSShuo Chenint main(int argc, const char* argv[]) 124aafef3ccSShuo Chen{ 125aafef3ccSShuo Chen if (argc < 2) 126aafef3ccSShuo Chen { 127aafef3ccSShuo Chen printf("Usage:\nServer: %s -s\nClient: %s server_hostname\n", argv[0], argv[0]); 128aafef3ccSShuo Chen return 0; 129aafef3ccSShuo Chen } 130aafef3ccSShuo Chen 131aafef3ccSShuo Chen if (strcmp(argv[1], "-s") == 0) 132aafef3ccSShuo Chen { 133aafef3ccSShuo Chen runServer(); 134aafef3ccSShuo Chen } 135aafef3ccSShuo Chen else 136aafef3ccSShuo Chen { 137aafef3ccSShuo Chen runClient(argv[1]); 138aafef3ccSShuo Chen } 139aafef3ccSShuo Chen} 140