Skip to content
Snippets Groups Projects
Commit d71364ec authored by Simon Oehrl's avatar Simon Oehrl
Browse files

small improvements

parent 1eeaae27
Branches main
No related tags found
No related merge requests found
......@@ -6,9 +6,10 @@ set(CXX_STANDARD_REQUIRED ON)
include(CPM.cmake)
CPMAddPackage("gh:OlivierLDff/asio.cmake@1.1.3")
CPMAddPackage("gh:fmtlib/fmt#9.1.0")
add_executable(sender sender.cpp)
target_link_libraries(sender PRIVATE asio::asio)
target_link_libraries(sender PRIVATE asio::asio fmt::fmt)
add_executable(receiver receiver.cpp)
target_link_libraries(receiver PRIVATE asio::asio)
#pragma once
#include <array>
#include <cstddef>
#include <cstdint>
constexpr std::size_t MAX_PACKET_SIZE = 65507;
struct Packet {
std::uint64_t id;
std::array<std::uint8_t, MAX_PACKET_SIZE - 8> payload;
};
static_assert(sizeof(Packet) >= MAX_PACKET_SIZE);
#include "packet.hpp"
#include <asio.hpp>
#include <asio/buffer.hpp>
#include <cstddef>
......@@ -8,6 +9,11 @@
using udp = asio::ip::udp;
using clk = std::chrono::steady_clock;
struct ReceivedContext {
std::uint64_t highest_id_received;
clk::time_point first_receive;
};
class Receiver {
public:
Receiver(std::uint16_t port)
......@@ -20,28 +26,53 @@ public:
private:
asio::io_context context;
udp::socket socket;
std::array<std::byte, 1024> data;
std::optional<clk::time_point> first_receive;
std::uint64_t bytes_received = 0;
Packet data;
std::optional<ReceivedContext> receive_data;
std::uint64_t total_bytes_received = 0;
std::uint64_t packets_received = 0;
std::uint64_t out_of_order_delivered_packets = 0;
clk::time_point last_print;
void receive() {
socket.async_receive(asio::buffer(data), [this](std::error_code ec,
std::size_t bytes_recvd) {
socket.async_receive(
asio::buffer(&data, MAX_PACKET_SIZE),
[this](std::error_code ec, std::size_t bytes_received) {
if (ec) {
std::cerr << ec.category().name() << ": " << ec.message() << std::endl;
std::cerr << ec.category().name() << ": " << ec.message()
<< std::endl;
} else {
bytes_received += bytes_recvd;
if (!first_receive.has_value()) {
first_receive = last_print = clk::now();
if (!receive_data.has_value()) {
// ignore first packet
receive_data.emplace(ReceivedContext{
.highest_id_received = data.id,
.first_receive = clk::now(),
});
} else {
const auto dt = clk::now() - *first_receive;
packets_received += 1;
total_bytes_received += bytes_received;
const auto dt = clk::now() - receive_data->first_receive;
const auto seconds =
std::chrono::duration_cast<std::chrono::duration<double>>(dt)
.count();
// std::cout << "ID: " << data.id << " length: " << bytes_received
// << std::endl;
//
if (data.id > receive_data->highest_id_received) {
if (data.id != receive_data->highest_id_received + 1) {
out_of_order_delivered_packets += 1;
}
receive_data->highest_id_received = data.id;
}
if (clk::now() - last_print > std::chrono::seconds(2)) {
std::cout << bytes_received * 8 / seconds / 1000.0 / 1000.0 << " Mbit/s" << std::endl;
std::cout << total_bytes_received * 8 / seconds / 1000.0 /
1000.0
<< " Mbit/s"
<< ", " << (data.id - packets_received)
<< " packets lost"
<< ", " << out_of_order_delivered_packets
<< " packets delivered out-of-order" << std::endl;
last_print = clk::now();
}
}
......
#include "packet.hpp"
#include <asio.hpp>
#include <asio/buffer.hpp>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <fmt/format.h>
#include <fmt/os.h>
#include <fstream>
#include <iostream>
using udp = asio::ip::udp;
......@@ -16,29 +20,47 @@ int main(int argc, char *argv[]) {
udp::endpoint endpoint =
*resolver.resolve(udp::v4(), argv[1], argv[2]).begin();
udp::socket s(context, udp::endpoint(udp::v4(), 0));
// udp::socket s(context, endpoint);
int packet_size = argc >= 4 ? std::stoi(argv[3]) : 1024;
int packet_size = argc >= 4 ? std::stoi(argv[3]) : MAX_PACKET_SIZE;
double time_between_packets = argc >= 5 ? std::stod(argv[4]) : 100;
std::cout << "packet size: " << packet_size << " byte" << std::endl;
std::cout << "packet size: " << packet_size << " bytes" << std::endl;
std::cout << "send interval: " << time_between_packets << " ms" << std::endl;
if (packet_size < 8) {
std::cerr << "packet size must be at least 8 bytes and at most "
<< MAX_PACKET_SIZE << " bytes" << std::endl;
return -1;
}
std::uint64_t bytes_sent = 0;
auto send_duration_file = fmt::output_file(fmt::format("send_durations_{}_{}.csv", packet_size, time_between_packets));
std::cout << "theoretical bandwidth: "
<< packet_size * 1000 * 8 / time_between_packets / 1000.0 / 1000.0
<< " Mbit/s" << std::endl;
const auto dt = std::chrono::duration_cast<clk::duration>(
std::chrono::duration<double, std::milli>(time_between_packets));
std::array<std::byte, 1024> data;
std::uint64_t skipped = 0;
Packet packet{.id = 0};
auto last = clk::now();
while (true) {
auto now = clk::now();
const auto now = clk::now();
if (now - last > dt) {
s.send_to(asio::buffer(data, packet_size), endpoint);
last += dt;
if (clk::now() - now > dt) {
s.send_to(asio::buffer(&packet, packet_size), endpoint);
packet.id += 1;
bytes_sent += packet_size;
const auto after_send = clk::now();
send_duration_file.print("{},{}\n", std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(after_send - now).count(), bytes_sent);
send_duration_file.flush();
while (last + dt < clk::now()) {
skipped++;
std::putchar('.');
std::cout.flush();
last += dt;
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment