Передача изображения с клиента на сервер при помощи boost asio и OpenCV
Пытаюсь передать изображение с клиента на сервер при помощи asio и OpenCV. В итоге при вызове функции async_read() на сервере, данная функция не вызывает handler и просто ьесконечно читает данные с клиента. Может кто подсказать, как правильно написать функцию async_read(), чтобы она прочитала все байты изображения из сокета и вызвала handler. Код клиента:
void async_read(boost::asio::streambuf& streambuf, boost::asio::ip::tcp::socket& socket)
{
boost::asio::async_read(socket, streambuf, [&](boost::system::error_code errorCode, std::uint16_t bytes_transfered){
std::istream istream(&streambuf);
std::cout << istream.rdbuf();
streambuf.consume(bytes_transfered);
socket.close();
});
}
void async_write(boost::asio::ip::tcp::socket& socket, std::vector<uchar>& photo_bytes)
{
boost::asio::async_write(socket, boost::asio::buffer(photo_bytes), [&](boost::system::error_code errorCode, std::uint16_t bytes_transfered){
std::cout << "Bytes transfered to server: " << bytes_transfered << std::endl;
});
}
int main(int argc, char* argv[]) {
std::string server = argv[1];
std::string port = argv[2];
std::string path_to_input_ph = argv[3];
std::string path_to_output_ph = argv[4];
boost::asio::io_context ioContext;
boost::asio::ip::tcp::resolver resolver(ioContext);
boost::asio::ip::tcp::resolver::results_type results = resolver.resolve(server, port);
// обработка изображения перед отправкой
cv::Mat srcmat;
std::vector<uchar> ImgBuf = {};
std::vector<int> quality_params{95, 95};
srcmat = cv::imread(path_to_input_ph);
cv::imencode(".jpg", srcmat, ImgBuf, quality_params);
boost::asio::ip::tcp::socket socket(ioContext);
boost::asio::async_connect(socket, results, [&](boost::system::error_code errorCode, boost::asio::ip::tcp::endpoint const& endpoint){
async_write(socket, ImgBuf);
});
boost::asio::streambuf streambuf;
async_read(streambuf, socket);
ioContext.run();
return 0;
}
Код сервера:
class Session : public std::enable_shared_from_this<Session> {
public:
Session(boost::asio::ip::tcp::socket &&socket) :
_socket(std::move(socket)) {
}
void start_session() {
std::cout << "Session started" << std::endl;
async_read();
}
private:
boost::asio::ip::tcp::socket _socket;
std::vector<uchar> ImgBuf;
cv::Mat mat;
void async_read() {
std::cout << "Async_read: started receiving bytes" << std::endl;
boost::asio::async_read(_socket, boost::asio::dynamic_buffer(ImgBuf, 65000), [&, self = shared_from_this()](boost::system::error_code errorCode,
std::uint16_t bytes_transfered) {
if (!errorCode) {
std::cout << "Bytes received: " << bytes_transfered << std::endl;
self->mat = cv::imdecode(ImgBuf, 95);
std::vector<int> compression_params;
compression_params.push_back(95);
compression_params.push_back(100);
if(!ImgBuf.empty())
cv::imwrite("/home/crestonix/CLionProjects/Gray_Image.jpg", mat, compression_params);
else
{
std::cout << "Error!";
}
async_write();
}
});
}
void async_write() {
std::cout << "Async_write: started transfering bytes" << std::endl;
boost::asio::async_write(_socket, boost::asio::buffer("Ty for image!"),
[&](boost::system::error_code errorCode, std::uint16_t bytes_transfered) {
if (!errorCode)
std::cout << "Bytes delivered" << bytes_transfered << std::endl;
_socket.close();
});
}
};
class Server {
public:
Server(boost::asio::io_context &io_context, std::uint16_t port) :
_ioc(io_context) {
std::cout << "Server constructed" << std::endl;
_acceptor.emplace(_ioc, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port));
}
void async_accept() {
_socket.emplace(_ioc);
_acceptor->async_accept(*_socket, [&](boost::system::error_code errorCode) {
std::cout << "Connection accepted" << std::endl;
auto session = std::make_shared<Session>(std::move(*_socket));
session->start_session();
async_accept();
});
}
private:
boost::asio::io_context &_ioc;
std::optional<boost::asio::ip::tcp::acceptor> _acceptor;
std::optional<boost::asio::ip::tcp::socket> _socket;
};
int main() {
boost::asio::io_context io_context;
Server server(io_context, 15001);
server.async_accept();
io_context.run();
return 0;
}