I'm using Boost asio to send and receive framed TCP messages. Does anyone know the correct way to use a streambuf?
Should I receive into one streambuf per connection, and parse the messages out to pass around in my application?
Or can I read into a single streambuf per message, and pass the streambufs themselves around?
Ideally I'd like an easy way of parsing individual data fields into/out of a message, such as using an istream/ostream.
Any advice appreciated!
Typically you don't want to pass the buffers around, you would want to deserialize the content into some form of internal message which is easier to pass around. You may want to investigate something like Google's protocol buffers or boost serialization etc. to allow you to send real messages over the wire.
Typically you'd want to use a buffer per connection, in the read handler deserialize the message, and reuse the buffer for the next read.
Related
I am new to Boost ASIO and have the following use case:
A client sends 1 MB data to a server. The server is able to process each byte of the data independent from the remaining data. My current solution is using the read_some and write_some methods for the server and client, respectively. This works well, but I would like to speed up my implementation by letting the server directly process the data while it still receives them. I already had a look at the documented examples but could not find one that fits my requirements.
I also wonder how I can take track how many bytes are received so far. I always have the same amount of data that the client sends.
Thank you in advance! Best regards.
I use custom code to create SSL connection over native Berkeley sockets interface. I need to wrap the resulted socket with iostream to use existing algorithms written in C++ with these sockets data.
Is there any easy way to do it without need to implement stream and streambuf from scratch?
I learned boost::iostreams and boost::asio.
I didn't find any way to wrap existing OpenSSL session with boost::asio. Or may be anyone knows how to do that?
After boost:asio I concentrated my research on boost:iostreams.
boost::iostreams looks like good idea, however, its problem is that it uses read buffering. So, if we need to read just 1 byte from SSL session, it asks the TCP device to read 4 kilobytes and results in timeout. From the other hand, when I set buffer size to 0, boost::iostreams start to call write method for each byte, so when I try to write 10 bytes to stream, it calls SSL_write 10 times. TCP device itself can not use write buffering, because there are no way to forward flush method to device, so application level protocol may expect that data is sent to another peer while the data remains in output buffer.
So, we need unbuffered read and buffered flushable write; is that possible with boost::iostreams?
I found solution myself.
First of all, it is required to mark the device as flushable. Because there are not ready-made template for such device, you have to inherit device<dual_use, Ch> and override its category with multiple inheritance:
struct category : device<dual_use, Ch>::category, flushable_tag
Now when you will call flush on stream, it will forward the call to your device.
Next step is to disable stream own buffering (i. e. call open with 2nd and 3rd parameters equal to 0).
In such configuration boost will write to device each byte of data separatelly. However, you can implement buffering on device level, and flush the buffer on flush call.
First, I want to say that I'm new with Boost asio, and I see a lot of examples but it remains things I don't understand.
I want to create a server, that will accept two clients (it will use two socket). The first client will send messages to the server and the server will send this message to the other client (yes, it is useless to use a server, but it's not the point here, I want to understand how all this work). This will happen until one of the client close.
So, I created a server, the server wait for the clients, and then, it must wait for the first client to send some message. And this is my question: what must I do after?
I thought I need to read the first socket, and then write on the second, and so and so, but how I know if the first client writed on the socket? Same, how I know if the second client read the second socket?
I don't need code, I just want to know the good way to do that.
Thanks a lot for reading!
When you perform async_read you specifify a callback which is going to be called whenever any data is read to the buffer ( you should provide the buffer also, check the async_read's documentation ). Respectively you should provide callback for the async_write to know when your data is already sent. So, from the server perspective, for the client which 'writes' you should do async_read, and for the second client which 'reads' you should do async write. With the offered dataflow client1->server->client2 it is hard to recognize which client the server should read from and which one is write to. It's up to you. You can choose the first connected client as writer and the second as reader, for example.
You might want to start with asio iostreams. It's a high-level iostream-like abstraction above asynchronous sockets.
P.S.: also, don't forget to run io_service.run() loop somewhere. Because all the asio callbacks are executed within that loop.
I am using Libevent library 2.0 for socket communication.
In order to add data to evbuffer, I am using evbuffer_add. The bufferevent stores the data in its internal buffer and transfers the data via socket using some predefined timeout and watermark settings.
My question is, is there any way to control the data transfer? Can we transfer the data explicitly any time and after any random number of bytes being written?
The idea behind this function is fire-and-forget. However, you can add a callback so that when the send finally happens, you can do some things:
evbuffer_add_cb
This doesn't allow you much control, but you can use it for some behaviors like appending the buffer.
I know it can be used to send/receive structured object from file,
but can it be used to send/receive sequences of structured object from a socket?
http://code.google.com/p/protobuf/
Protocol Buffers is a structured data serialization (and de-serialization) framework. It is only concerned with encoding a selection of pre-defined data types into a data stream. What you do with that stream is up to you. To quote the wiki:
If you want to write multiple messages
to a single file or stream, it is up
to you to keep track of where one
message ends and the next begins. The
Protocol Buffer wire format is not
self-delimiting, so protocol buffer
parsers cannot determine where a
message ends on their own. The easiest
way to solve this problem is to write
the size of each message before you
write the message itself. When you
read the messages back in, you read
the size, then read the bytes into a
separate buffer, then parse from that
buffer.
So yes, you could use it to send/receive multiple objects via a socket but you have to do some extra work to differentiate each object stream.
I'm not familiar with protobuf, but the documentation says you can create a FileInputStream (which can then be used to create a CodedInputStream) using a file descriptor. If you're on a system that supports BSD sockets, you should presumably be able to give it a socket file descriptor rather than an ordinary one.
Protocol Buffers does not handle any surrounding network/file I/O operations. You might want to consider using Thrift, which includes socket communication libraries and server libraries with the serialization/deserialization.