Клиент-сервер быстрой передачи данных (изображений) с использованием Boost Asio

Я относительно новичок в сетевом программировании и у меня есть несколько вопросов по передовым методам непрерывной быстрой передачи данных (изображений) между клиентом и сервером с использованием Boost Asio. Важный момент, мы не можем применять сжатие, которое снижает качество изображения. Мы используем выделенную сеть (54 Мбит) без трафика, кроме нашего. Нам порекомендовали использовать Boost Asio, так как он, кажется, подходит для наших нужд. Однако, поскольку Boost является мощным средством, оно является сложной задачей для неопытных разработчиков (Boost), таких как я.

Мы хотим разработать инструмент, как можно более простой, который непрерывно отправляет данные изображения с максимально возможной скоростью между клиентом и сервером. В основном это потоковая передача. Мы бы предпочли использовать TCP, но если бы у нас был значительный прирост производительности с UDP, мы не возражали бы время от времени терять пакеты данных.

Данные представляют собой буфер беззнаковых символов (640x480 пикселей = 307200 байт = 2,34 Мбит, монохромный ).

Я начал с руководств по Asio и поигрался с проектами синхронизации, async, UDP, TCP. На данный момент я могу отправлять данные со скоростью ~ 10 кадров в секунду, ~ 0,1 мс на изображение с TCP и ~ 13 кадров в секунду с UDP. Это слишком медленно. Я ожидал, что отправка 2,4 Мбит в сети 54 Мбит будет намного быстрее.

Сегодня я не использую сериализацию, архивирование, сжатие (zip) и т. Д. Моих данных. Я думаю, что это улучшит передачу, но мне интересно, нужно ли мне оправдать свои ожидания и / или мне нужно полностью изменить свой подход?

Является ли сериализация данных способом потоковой передачи данных с помощью Asio? Сможет ли сжатие zip значительно улучшить передачу? Существуют ли альтернативные подходы или структуры?

Пример кода TCP-сервера

// sends data whenever it receives a request by the client
int main(int argc, char* argv[])
{
init_image_buffer();
try
{
    boost::asio::io_service io_service;

    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 13));

    for (;;)
    {
        tcp::socket socket(io_service);
        acceptor.accept(socket);

        boost::system::error_code ignored_error;
        boost::asio::write(socket, boost::asio::buffer(image_buffer),
            boost::asio::transfer_all(), ignored_error);
    }
}
catch (std::exception& e)
{
    std::cerr << e.what() << std::endl;
}

return 0;
}

Пример кода TCP-клиента

Я понимаю, что этот код не оптимален. Но я не мог понять, как оставаться на связи и запрашивать новые данные с помощью такого подхода.

int main(int argc, char* argv[])
{
Clock clock;
clock.Initialise();

float avg = 0.0;
float min = 1000000.0;
float max = 0.0;
float time = 0.0;

// sending multiple images
for(int j=0;j<IMAGE_COUNT;j++){

    try
    {
        clock.GetTime();
        if (argc != 2)
        {
            std::cerr << "Usage: client <host>" << std::endl;
            return 1;
        }

        boost::asio::io_service io_service;

        tcp::resolver resolver(io_service);
        tcp::resolver::query query(argv[1], 13);
        tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
        tcp::resolver::iterator end;

        tcp::socket socket(io_service);
        boost::system::error_code error = boost::asio::error::host_not_found;

        while (error && endpoint_iterator != end)
        {
            socket.close();
            socket.connect(*endpoint_iterator++, error);
        }
        if (error)
            throw boost::system::system_error(error);

        // we read all received data but do NOT save them into a dedicated image buffer
        for (;;)
        {
            boost::array<unsigned char, 65536> temp_buffer;
            boost::system::error_code error;

            size_t len = socket.read_some(boost::asio::buffer(temp_buffer), error);

            if (error == boost::asio::error::eof)
                break; // Connection closed cleanly by peer.
            else if (error)
                throw boost::system::system_error(error); // Some other error.

        }

        time = clock.GetTime();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    // calculate some time transfer statistics
    avg+=time;
    if(time < min) min = time;
    if(time > max) max = time;

}
std::cout << "avg: " << avg/(float)IMAGE_COUNT << " freq: " << 1.0/(avg/(float)IMAGE_COUNT) << std::endl;
std::cout << "min: " << min << " max: " << max << std::endl;

return 0;
 }
5
задан Jason Plank 18 October 2011 в 20:49
поделиться