views:

961

answers:

5

Hello. I am trying to use some socket network programming in C++. I am trying to send the text "Hello World!" to a server using the C++ send() function. At first, I set the buffer to the size of 13 since "Hello World!" altogether is 12 characters (you have to make it one more than the character count). The send function only sends the characters to the server if I send it about 7 times. And when it does finally come to the server it looks like this:

"Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!"

Now here is the funny part. The "Hello World!" sentence sends immediately if I set the buffer size to 256 (char buffer[256];). When it comes to the server like that though, it shows "Hello World!" with a whole bunch of space after the two words. Why is this happening and if possible, how can I fix it? Please let me know.

Thanks

+6  A: 

When you call read (or receive) with your buffer to read from the socket, an integer value is returned that specifies the number of bytes read. You should only take that much from the buffer. The rest is irrelevant:

int count = read(...);
// buffer[0 .. count - 1] contains the appropriate data.
Mehrdad Afshari
And just to let you know, the server receiving the data is made in C#
QAH
QAH: This is also true for C# sockets, Socket.Receive method.
Mehrdad Afshari
+4  A: 

Buffers exist to store data until you are ready to send it. You have a send buffer size of 256. Until 256 characters are transmitted through the buffer, your data won't be sent to the other side. You can fix this by calling a flush method on your buffer when you know you are ready to send.

To be clear, you are buffering internally, then the OS (or library) is buffering again when you call send() and pass some data.

If you get more specific with what library you are using and maybe include a code snippet, we can probably find the right buffer flush function to send you on your way with.

Alternatively, if you are in *nix, just turn off Nagle's algorithm so that the OS won't buffer your small packets. Or, when you set up you socket, make sure to use the TCP_NODELAY option

Zak
+6  A: 

Nagle's algorithm usually is turned on by default. This will combine several small packets into one. Turning Nagle's algorithm off will allow small packets to be sent immediately.

zooropa
A: 

Assuming this is a SOCK_STREAM socket, the important thing to be aware of is that the underlying TCP protocol does not maintain any segment boundaries. That is, when you call send() multiple times, all of the data you sent may very easily be returned by a single recv() call at the other end. Or, the data sent in one send() call may be returned in multiple recv()s at the other end, e.g. if some packets got delayed due to network congestion. This is fundamental to the design of TCP, and your application must be designed accordingly.

Also, as noted by Mehrdad, the recv() call returns the number of bytes that were read off the wire. Anything after that point in the buffer is garbage, and the data is not zero-terminated.

A SOCK_DGRAM socket uses UDP underneath, which is entirely packet-oriented, as opposed to stream-oriented like TCP. However, UDP does not guarantee reliability (the U stands for Unreliable), so you have to handle lost, duplicated, out-of-order etc. packets yourself. This is a lot harder than stream-oriented I/O.

ceo
UDP is the User Datagram Protocol - it has nothing about unreliable in its name. You're correct that it is relatively unreliable, though :)
Steven Schlansker
A: 

Socket programming is tedious, error prone and non portable. Start using libraries like Boost or ACE that shield you from the low level C APIs and provide you with platform independent abstractions.

lothar