roundtrip_udp.cc revision 24ca08a8
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();
87aafef3ccSShuo Chen      int nw = sock.write(&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 };
104aafef3ccSShuo Chen    int nr = sock.read(&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    {
114aafef3ccSShuo Chen      perror("send 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