views:

309

answers:

3

Hi

As there several ways to exchange data in the form of strings over sockets, such as e.g:

  • using functions like:
    1) sprintf() and sscanf()
    2) snprintf() and sscanf()
    3) printf() and strtof()

  • or converting to char and then pass it as an array

I would appreciate if you could suggest which way and why is efficient and better than others, or if there is another way not mentioned above. At the moment I am using the simplest way , I mean sprintf() and sscanf() functions. But I read on the web that e.g. using snprintf() function is more safe.

Thanks for your time and replies-

A: 

Have a look at Serialization—How to Pack Data.

It's easy enough to send text data across the network, you're finding, but what happens if you want to send some "binary" data like ints or floats? It turns out you have a few options.

  1. Convert the number into text with a function like sprintf(), then send the text. The receiver will parse the text back into a number using a function like strtol().
  2. Just send the data raw, passing a pointer to the data to send().
  3. Encode the number into a portable binary form. The receiver will decode it.
Nick D
Thanks for your reply. For binary, there is a not a problem as I am using google's protocol buffers as the exchange is between different OSs.
make
So, are you suggesting that using sprintf() and strtol() is good enough?
make
@mk, maybe it's a bit slow but it's not a bad option IMO.
Nick D
I'm confused - is this question related to sending Protocol Buffer messages over sockets? If so, aren't you using the provided IO classes to encode/decode? http://code.google.com/apis/protocolbuffers/docs/reference/cpp/index.html#google.protobuf.io
therefromhere
@therefromhere, no, it is not about sending data in binary mode, but in string (ASCII)... thanks for reply <br>@Nick D, what is then the fastest way (I mean in ASCII mode) ? thanks!
make
+1  A: 

in C++ you can also use StringStream

stringstream ss;
 int i = 1;
 float f = "1.0";
 char separtor = ';';

 ss << i << separtor  << f;

you can then extract the string with ss.str().c_str()

ss.str().c_str() will result in the case above with

"

1;1.0

"

Alon
thanks for your reply, that is very interesting. does this work when communicating between different OSs?
make
I've edited my response to produce a constant char result
Alon
thanks! Actually I read on the net that using stringstream is useless, see http://www.flamingspork.com/blog/2009/08/04/stringstream-is-completely-useless-and-why-c-should-have-a-snprintf/ , thanks again for your help
make
the author arguments are mostly concentrated around specific cases, I have used string Stream extensively on my past projects and found them to be far removed from useless. But this is a completely subjective issue :-)
Alon
+1  A: 

if you just want to send strings, you can get away with something like this; it's serialization in a simple form: a header containing the size of the data following.. (pseudo-code)

Send( socket, const string& str )
{
  const size_t len = str.length();
  send( socket, &len, sizeof( len ) );
  send( socket, str.data(), len );
}

Receive( socket, string& str )
{
  size_t len;
  receive( socket, &len, sizeof( len ) );
  str.resize( len );
  receive( socket, str.data(), len );
}

Edit: see comment 1, a faster Send method would be

Send( socket, const string& str, rawmemory& packet )
{
  const size_t len = str.length();
  packet.Reserve( len + sizeof( len ) );
  packet.ResetOffset();
  packet.CopyFrom( &len, sizeof( len ) );
  packet.CopyFrom( str.data(), len );
  send( socket, packet.Data(), packet.Length() );
}
stijn
doing 2 sends means that two packets will be sent. You would be better off using some scatter gather mechanism and the all the data sent in a single packet. (I am assuming you are using TCP here)
doron
@deus-ex-machina399: Only if you have set the TCP_NODELAY flag on the socket.
drspod
you're both right; I use similar code myself and I indeed reserve an extra buffer in which I create the single packet, since I use TCP_NODELAY in a couple of projects where many rather small packets have to be sent at rather high rates
stijn
the question is not related to seliarization ...but to how to send data in the form of string (ASCII mode). But why you are 2x send and receive? if the data are not received the second send wouldn't executed, is this right?
make
if you just send a string, the remote side does not know on beforehand how large the string is, in other words the receiver must either preallocate enough or receive in blocks. To get around this, my example first sends the size of the data, then the data itself. Now, from your responses here I'm starting to think your question is actually about converting to/from string and has nothing to do with how the data is sent, am I correct? in that case, the question has nothing to do with sockets. Maybe provide an example of hat exactly you're trying to achieve.
stijn
not really! just exchanging data as ASCII strings. thanks for your reply
make