How to upload a file with ASIO
Hello, I have successfully implemented clients and servers, both in the Windows side and the Linux side. So far, the Windows client passes a set of parameters and the servers returns some text which is displayed on the client's screen. That part is working perfectly. My next challenge is to upload a whole file(s) from the client to the server and would like hear any tips, caveats from experienced ASIO users. Thanks to everyone for sharing their expertise. Regards, -Ramon
I should add that I have decided to standardize on synchronous TCP transfers. My experience with UDP was terrible. TIA, -Ramon Ramon F Herrera wrote:
Hello,
I have successfully implemented clients and servers, both in the Windows side and the Linux side. So far, the Windows client passes a set of parameters and the servers returns some text which is displayed on the client's screen. That part is working perfectly.
My next challenge is to upload a whole file(s) from the client to the server and would like hear any tips, caveats from experienced ASIO users.
Thanks to everyone for sharing their expertise.
Regards,
-Ramon
On Tuesday 03 November 2009 04:37:08 pm Ramon F Herrera wrote:
Hello,
I have successfully implemented clients and servers, both in the Windows side and the Linux side. So far, the Windows client passes a set of parameters and the servers returns some text which is displayed on the client's screen. That part is working perfectly.
My next challenge is to upload a whole file(s) from the client to the server and would like hear any tips, caveats from experienced ASIO users.
Thanks to everyone for sharing their expertise.
Regards,
-Ramon
Hello, It would be interesting to know *how* you exactly transfer the information at hand and then build a solution from there. Anyways, I use ASIO in conjunction with boost::serialization. There is an example on the ASIO website. I found that combination extremely handy. With this approach one could easily transfer any kind of data, for example in a std::vector. hth, Benjamin
Benjamin Sobotta wrote:
Hello,
It would be interesting to know *how* you exactly transfer the information at hand and then build a solution from there.
Anyways, I use ASIO in conjunction with boost::serialization. There is an example on the ASIO website. I found that combination extremely handy. With this approach one could easily transfer any kind of data, for example in a std::vector.
hth,
Benjamin
Hi Benjamin, Find below the relevant snippets of the client and the server code. As you can see, I keep on sending parameters, separated by newlines. Two consecutive newlines denote end of input. This obviously does not scale to a more complex transfer (i.e., a complete binary file). Thanks for your kind assistance, -Ramon ---------------------------------------- Client: // stream boost::asio::streambuf buf; std::ostream net_out(&buf); // Display the arguments if (debug()) cout << "client pushing " << argc - 1 << " arguments" << endl; for (int i = 1; i < argc; i++) { net_out << argv[i] << endl; if (debug()) cout << "arg[" << i << "], " << argv[i] << " was pushed" << endl; } net_out << endl; boost::asio::write(socket, buf); while (true) { boost::array<char, 128> buf; boost::system::error_code error; size_t len = socket.read_some(boost::asio::buffer(buf), 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. cout.write(buf.data(), len); } ---------------------------------------- Server: while (true) { tcp::socket socket(io_service); acceptor.accept(socket); /////////////////////////////////////////////////////////////////////////////////// boost::asio::streambuf buf; boost::system::error_code error; // read till end-of-args marker boost::asio::read_until(socket, buf, "\n\n"); // extract args from buf std::istream net_in(&buf); while (getline(net_in, next_line)) { if (next_line.length()) client_argv.push_back(next_line); } if (debug()) cout << client_argv.size() << " arguments received by server" << endl; /////////////////////////////////////////////////////////////////////////////////// ostringstream response; it_takes_two_to_tango(client_argv, tx, db, response); client_argv.clear(); string message = response.str(); // if (debug()) cout << "Deliver to server:" << endl << message << endl; boost::system::error_code ignored_error; boost::asio::write(socket, boost::asio::buffer(message), boost::asio::transfer_all(), ignored_error); } }
On Tuesday 03 November 2009 05:36:50 pm Ramon F Herrera wrote:
Benjamin Sobotta wrote:
Hello,
It would be interesting to know *how* you exactly transfer the information at hand and then build a solution from there.
Anyways, I use ASIO in conjunction with boost::serialization. There is an example on the ASIO website. I found that combination extremely handy. With this approach one could easily transfer any kind of data, for example in a std::vector.
hth,
Benjamin
Hi Benjamin,
Find below the relevant snippets of the client and the server code. As you can see, I keep on sending parameters, separated by newlines. Two consecutive newlines denote end of input. This obviously does not scale to a more complex transfer (i.e., a complete binary file).
Thanks for your kind assistance,
-Ramon
---------------------------------------- Client:
// stream boost::asio::streambuf buf; std::ostream net_out(&buf);
// Display the arguments
if (debug()) cout << "client pushing " << argc - 1 << " arguments" << endl;
for (int i = 1; i < argc; i++) { net_out << argv[i] << endl; if (debug()) cout << "arg[" << i << "], " << argv[i] << " was pushed" << endl; }
net_out << endl;
boost::asio::write(socket, buf);
while (true) {
boost::array<char, 128> buf; boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), 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.
cout.write(buf.data(), len); }
---------------------------------------- Server:
while (true) {
tcp::socket socket(io_service); acceptor.accept(socket);
/////////////////////////////////////////////////////////////////////////// ////////
boost::asio::streambuf buf; boost::system::error_code error;
// read till end-of-args marker boost::asio::read_until(socket, buf, "\n\n");
// extract args from buf std::istream net_in(&buf);
while (getline(net_in, next_line)) {
if (next_line.length()) client_argv.push_back(next_line); }
if (debug()) cout << client_argv.size() << " arguments received by server" << endl;
/////////////////////////////////////////////////////////////////////////// ////////
ostringstream response;
it_takes_two_to_tango(client_argv, tx, db, response); client_argv.clear();
string message = response.str();
// if (debug()) cout << "Deliver to server:" << endl << message << endl;
boost::system::error_code ignored_error; boost::asio::write(socket, boost::asio::buffer(message), boost::asio::transfer_all(), ignored_error); } }
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Hello! Sorry, that my reply took so long as I was very busy. I think the way too transfer binary data is to first send, say, an unsigned integer indicating the number of bytes to come. Here a little snippet of code: Say your binary data is contained in a std::string data, then I would try something like the following: unsigned int outbound_message_size = data.size(); std::vector<boost::asio::const_buffer> buffers; buffers.push_back(boost::asio::buffer((char*)(&outbound_message_size), sizeof(unsigned int))); buffers.push_back(boost::asio::buffer(data, outbound_message_size)); boost::system::error_code ignored_error; boost::asio::write(socket, buffers, boost::asio::transfer_all(), ignored_error); Then, on the receiving side you always read sizeof(unsigned int) bytes first and see how much data is waiting. Btw, I have to point out that I'm also new to ASIO and there maybe more elegant solutions for the problem. HTH, Ben
participants (2)
-
Benjamin Sobotta
-
Ramon F Herrera