|
|
- #include <chrono>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <string.h>
- #include <sstream>
- #include <string>
- #include <endian.hpp>
- #include <network.hpp>
- #include <array>
- #include <thread>
- #include <algorithm>
-
- using namespace std::chrono_literals;
-
- int main(int, char** argv){
- int64_t offset=0;
- std::array<int64_t, 4096> offsets;
- std::array<int64_t, 4096> offsets_smooth;
- std::array<int64_t, 4096> offset_variations;
- size_t pos = 0;
- int64_t max_offset_variation;
- int64_t max_oscillation = 0;
- int64_t min_ever = std::numeric_limits<int64_t>::max();
- int64_t max_ever = 0;
-
- std::stringstream ip_stream{argv[1]};
- std::array<uint8_t, 4> ip;
- std::string token;
- std::getline(ip_stream, token, '.');
- ip[0] = std::stoi(token);
- std::getline(ip_stream, token, '.');
- ip[1] = std::stoi(token);
- std::getline(ip_stream, token, '.');
- ip[2] = std::stoi(token);
- std::getline(ip_stream, token, '.');
- ip[3] = std::stoi(token);
-
- uint16_t port = std::stoi(argv[2]);
-
-
- auto soc = socket(AF_INET, SOCK_DGRAM, 0);
- struct sockaddr_in server;
- server.sin_family = AF_INET;
- server.sin_addr.s_addr = *(in_addr_t*)ip.data();
- server.sin_port = htons(port);
-
-
- struct timeval tv;
- tv.tv_sec = 5;
- tv.tv_usec = 0;
- setsockopt(soc, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
-
- std::cerr << "Connecting..." <<std::endl;
- connect(soc, (struct sockaddr*)&server, sizeof(server));
-
-
- req_rep buffer;
-
- uint64_t cnt = 0;
- uint64_t old_time = 0;
-
- while(true)
- {
- uint64_t tmp;
- buffer.id = 16;
-
- buffer.client_ts = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
- send(soc, (void*)&buffer, (socklen_t)sizeof(req_rep), 0);
- recv(soc, (void*)&buffer, (socklen_t)sizeof(req_rep), 0);
- if(buffer.server_ts != old_time)
- {
- tmp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count() - buffer.client_ts;
- int64_t n_offset = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count() - buffer.server_ts;
- n_offset /= 2;
- offset_variations[pos] = ((long long)(offset-n_offset));
- if(cnt != 0)
- {
- offsets[pos] = n_offset;
- } else {
- offsets.fill(n_offset);
- offsets_smooth.fill(n_offset);
- }
- max_offset_variation = std::max(*std::max_element(offset_variations.begin(), offset_variations.end()), std::abs((int64_t)*std::min_element(offset_variations.begin(), offset_variations.end())));
- offset = (
- 7 * (std::accumulate(offsets_smooth.begin(), offsets_smooth.end(), 0)/offsets_smooth.size())
- + std::accumulate(offsets.begin(), offsets.end(), 0)/offsets.size()
- ) / 8;
- offsets_smooth[pos] = offset;
- pos=(pos+1)%offset_variations.size();
- if(cnt > offsets.size()*2)
- {
- for(auto i : offsets_smooth)
- for(auto j : offsets_smooth)
- {
- max_oscillation = std::max(
- std::abs(i-j),
- max_oscillation
- );
- }
- min_ever = std::min(min_ever, offset);
- max_ever = std::max(max_ever, offset);
- }
- else if (cnt < offsets.size()) {
- offsets_smooth[pos] = n_offset;
- }
- old_time = buffer.server_ts;
- std::cout << cnt << "\t"<< min_ever << "\t" << offset << "\t" << max_ever << "\t" << max_oscillation << "\t" << offset-n_offset << "\t" << max_offset_variation <<std::endl;
- }
- cnt++;
- //std::this_thread::sleep_for(6ms);
- }
- }
|