我有4MB的圖像,必須通過以太網發送。圖像來自一臺計算機,X86_64,它生成它們,併發送到另一臺計算機,ARM。圖像以兩位數幀速率生成,我使用cat 6a電纜確保以合理的速度獲得足夠的數據。我無法理解什麼樣的實用程序提升可讓我使用通過UDP發送任意大小的數據,並在另一端接收它。兩臺電腦都安裝了Boost,兩者都是linux(但不同的發行版)。個人圖像丟失並不重要,但重要的是要發送或拒絕整個圖像。通過boost :: asio :: udp以高數據速率發送圖像數據?
- 我是否必須手動分段要發送的數據?
- 如果是這種情況,我該如何處理圖像丟包?就像我將如何分辨我的圖像的結尾是什麼?我是否必須爲每個數據包添加與其對應的圖像行?
- 增強是否有實用程序來處理UDP上的任意數據發送?
試圖做到這一點後,我的自我(用行標識符標記每行)似乎我過度飽和一些緩衝區(標記是順序的,直到某個點,他們開始跳躍數量單調,所以沒有重新排序,但數據包丟失)注意這是在本地主機,所以我不知道我應該期待什麼。
我似乎無法找到解決大量圖像丟失的方法,但我不確定這是否僅僅是因爲網絡電纜限制(儘管發送到本地主機並在本地主機上接收?)。
我會轉移到TCP,但我需要放心,我可以在另一端通過直接以太網連接可靠地獲得200MB/s。圖像開始發送之前的時間並不比給定秒內的整體吞吐量重要。
略微簡化的代碼對於由此製成:
發送圖像
// sender.cpp
#include <thread>
#include <chrono>
#include <algorithm>
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include "PgmImage.h"
using boost::asio::ip::udp;
const std::string &host = "localhost";
const std::string &port = "8000";
const int image_width = 2048;
const int image_height = 2048;
int main() {
try {
boost::asio::io_service io_service;
udp::resolver resolver(io_service);
udp::resolver::query query(udp::v4(), host, port);
udp::endpoint receiver_endpoint = *resolver.resolve(query);
udp::socket send_socket(io_service);
send_socket.open(udp::v4());
boost::array<std::uint16_t, 2> send_header_buffer;
boost::array<std::uint8_t, image_height + 2> send_row_buffer;
auto time1 = std::chrono::high_resolution_clock::now();
for (int j = 0; j < 1000; ++j) {
for (const auto &file_path : file_path_list) {
// reads in image and has a vector member of char.
PgmP5Image image("../short_armcam_clip/" + file_path);
send_header_buffer = {image.width(), image.height()};
send_socket.send_to(boost::asio::buffer(send_header_buffer), receiver_endpoint);
for (std::uint16_t i = 0; i < image_height; i++) {
send_row_buffer[0] = static_cast<std::uint8_t>(i >> 8);
send_row_buffer[1] = static_cast<std::uint8_t>(i);
std::copy(&image.getRawBytes()[i * image_width],
&image.getRawBytes()[i * image_width + image_width], &send_row_buffer[2]);
send_socket.send_to(boost::asio::buffer(send_row_buffer), receiver_endpoint);
if (i % 64 == 0) {
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(1));
}
}
}
}
auto time2 = std::chrono::high_resolution_clock::now();
std::cout << "took : " << std::chrono::duration_cast<std::chrono::milliseconds>(time2 - time1).count() << "millis"
<< std::endl;
}
catch (std::exception &e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
接收圖像
// receiver.cpp
#include <ctime>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <iostream>
using boost::asio::ip::udp;
int main() {
try {
boost::asio::io_service io_service;
udp::socket socket(io_service, udp::endpoint(udp::v4(), 8000));
udp::endpoint remote_endpoint;
boost::array<std::uint16_t, 2> recv_header_buffer;
boost::array<std::uint8_t, 2050> recv_row_buffer;
int num_recieved = 0;
while (true) {
boost::system::error_code error;
socket.receive_from(boost::asio::buffer(recv_header_buffer), remote_endpoint, 0, error);
if (error && (error != boost::asio::error::message_size)) {
throw boost::system::system_error(error);
}
int width = recv_header_buffer[0];
int height = recv_header_buffer[1];
std::cout << "width : " << width << " height : " << height << std::endl;
for (int i = 0; i < height; ++i) {
socket.receive_from(boost::asio::buffer(recv_row_buffer), remote_endpoint, 0, error);
if (error && (error != boost::asio::error::message_size)) {
throw boost::system::system_error(error);
}
std::uint16_t row = (recv_row_buffer[0] << 8) + recv_row_buffer[1];
std::cout << "row : " << row << " processed " << std::endl;
std::cout << "i : " << i << std::endl;
if (row != i) {
break;
}
if (i == 2047) {
num_recieved += 1;
std::cout << "Num received: " << num_recieved << std::endl;
}
}
}
}
catch (std::exception &e) {
std::cerr << e.what() << std::endl;
}
}
經過測試TCP之後,我獲得了奇怪的性能提升,所以我現在切換到TCP – snb
這是因爲TCP確實是流式傳輸。您可以通過使用套接字TCP窗口大小來優化您的應用程序以獲得最佳吞吐量。 https://stackoverflow.com/questions/14381303/increasing-tcp-window-size –