Modify an asio echo server so that it does not send message back to client
Hi, I am writing a simple server that is listening to binary data bucket being sent by a client. I am basing the prototype server on the following: http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/example/cpp03/echo/... I am wonder what is the correct way to modify the example so that it does not echo the result back to the client. The amount of binary data sent are substantial, more importantly, the client has no way to handle the incoming data on the socket. Cheers -- Nicholas Yue Graphics - Arnold, Alembic, RenderMan, OpenGL, HDF5 Custom Dev - C++ porting, OSX, Linux, Windows http://au.linkedin.com/in/nicholasyue https://vimeo.com/channels/naiadtools
So if I understand you correctly, you just want to keep reading the data asynchronously and process them without sending them back? Basically remove the ba::async_write from handle_read them, put your processing code there within the if(!error)-Block instead and then after processing just start another read the same way it is done in handle_write (you don't need handle_write anymore then): .. if (!error) { process(data_); socket_.async_read_some(boost::asio::buffer(data_, max_length), boost::bind(&session::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholder::bytes_transferred)); } .. Am 09.06.2015 um 21:22 schrieb Nicholas Yue:
Hi,
I am writing a simple server that is listening to binary data bucket being sent by a client.
I am basing the prototype server on the following:
http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/example/cpp03/echo/...
I am wonder what is the correct way to modify the example so that it does not echo the result back to the client. The amount of binary data sent are substantial, more importantly, the client has no way to handle the incoming data on the socket.
Cheers -- Nicholas Yue Graphics - Arnold, Alembic, RenderMan, OpenGL, HDF5 Custom Dev - C++ porting, OSX, Linux, Windows http://au.linkedin.com/in/nicholasyue https://vimeo.com/channels/naiadtools
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Hi Jonas,
Yes, I want to keep reading data an process them. Here is my
implementation base on my understanding of your suggestion:
class session
{
public:
session(boost::asio::io_service& io_service)
: socket_(io_service)
{
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
socket_.async_read_some(boost::asio::buffer(data_, max_length),
boost::bind(&session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
std::cout << boost::format("handle_read bytes_transferred ='%1%'") %
bytes_transferred << std::endl;
process(data_);
socket_.async_read_some(boost::asio::buffer(data_, max_length),
boost::bind(&session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
std::cout << boost::format("handle_read data_ ='%1%'") % data_ << std::endl;
}
else
{
delete this;
}
}
void process(char *data)
{
std::cout << boost::format("process data_ ='%1%'") % data_ << std::endl;
}
private:
tcp::socket socket_;
enum { max_length = 1024 };
char data_[max_length];
};
Cheers
On 9 June 2015 at 12:35, Jonas Stöhr
So if I understand you correctly, you just want to keep reading the data asynchronously and process them without sending them back? Basically remove the ba::async_write from handle_read them, put your processing code there within the if(!error)-Block instead and then after processing just start another read the same way it is done in handle_write (you don't need handle_write anymore then):
.. if (!error) { process(data_); socket_.async_read_some(boost::asio::buffer(data_, max_length), boost::bind(&session::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholder::bytes_transferred)); } ..
Am 09.06.2015 um 21:22 schrieb Nicholas Yue:
Hi,
I am writing a simple server that is listening to binary data bucket being sent by a client.
I am basing the prototype server on the following:
http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/example/cpp03/echo/...
I am wonder what is the correct way to modify the example so that it does not echo the result back to the client. The amount of binary data sent are substantial, more importantly, the client has no way to handle the incoming data on the socket.
Cheers -- Nicholas Yue Graphics - Arnold, Alembic, RenderMan, OpenGL, HDF5 Custom Dev - C++ porting, OSX, Linux, Windows http://au.linkedin.com/in/nicholasyue https://vimeo.com/channels/naiadtools
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Nicholas Yue Graphics - Arnold, Alembic, RenderMan, OpenGL, HDF5 Custom Dev - C++ porting, OSX, Linux, Windows http://au.linkedin.com/in/nicholasyue https://vimeo.com/channels/naiadtools
On 10/06/2015 09:11, Nicholas Yue wrote:
Yes, I want to keep reading data an process them. Here is my implementation base on my understanding of your suggestion: [...] void handle_read(const boost::system::error_code& error, size_t bytes_transferred) { if (!error) { std::cout << boost::format("handle_read bytes_transferred ='%1%'") % bytes_transferred << std::endl; process(data_); socket_.async_read_some(boost::asio::buffer(data_, max_length), boost::bind(&session::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); std::cout << boost::format("handle_read data_ ='%1%'") % data_ << std::endl; } else { delete this; } }
void process(char *data) { std::cout << boost::format("process data_ ='%1%'") % data_ << std::endl; }
You need to pass the bytes_transferred to process as well, so that it knows how much data was actually read and therefore how much of data_ is actually valid. Don't forget that this may be less than max_length and may be different from what the client actually sent (ie. data sent in one chunk may be received in multiple chunks).
On 2015-06-09 5:14 PM, Gavin Lambert wrote:
You need to pass the bytes_transferred to process as well, so that it knows how much data was actually read and therefore how much of data_ is actually valid. Don't forget that this may be less than max_length and may be different from what the client actually sent (ie. data sent in one chunk may be received in multiple chunks).
Thanks Gavin. I now have a process() method with the bytes_transferred parameter. Newbie question, how do I know the last chunk has been sent, so that I can now process the data (which will be binary) ? Is there some simple example which illustrate this I can refer to ? Cheers Nicholas Yue
On 11/06/2015 11:56, Nicholas Yue wrote:
I now have a process() method with the bytes_transferred parameter.
Newbie question, how do I know the last chunk has been sent, so that I can now process the data (which will be binary) ?
Is there some simple example which illustrate this I can refer to ?
There isn't any inherent way to know. TCP is a stream protocol -- you just receive a continuous stream of bytes with no demarcation of any kind. You will need to define something at the application layer of the protocol to decide when a logical unit is complete, typically either by inserting some delimiter that you know can never occur mid-message or by sending the length of the following data early on. Note that ASIO does provide some helper methods for these scenarios -- instead of using async_read_some, which just returns data as it becomes available, you can use asio::async_read (which you can tell to not return until it has read a specific number of bytes) or asio::async_read_until (read until a specific delimiter). (It's tricky, though not impossible, to do a combination of the two -- but it's something you should avoid if you have a choice.) So for a line-based protocol you could async_read_until a CRLF (or just LF, depending on the other end), or for a binary protocol that sends a 4-byte length followed by a payload you could async_read 4 bytes to get the length, then async_read that many bytes to get the payload.
participants (3)
-
Gavin Lambert
-
Jonas Stöhr
-
Nicholas Yue