views:

77

answers:

5

Is it possible to have winsock's send function block until the packet being sent is received at the other end?

My end goal is to be able to send 5-20mb files while still being able to send small 1kb packets on the same connection. So I was thinking I would have it block until the receiver receives the packet. That way if another small packet is queued it wont be stuck waiting for the rest of the large file to be transferred.

A: 

No. And you don't need to do this.

Steven Sudit
So if I send a large packet and then a smaller one, will tcp send the small while it is still sending the large one?
TCP is just a stream, if you do one send() call, it might take multiple recv() calls to read that data on the other side. Conversely, several send() calls might be merged, and read with one recv() calls. You have to build your own protocol on top of TCP if you want to send "packets", or get a reply when a packet/message has been received.
nos
Are you sure? I thought the point of tcp is that it does that kind of management for you. I have never had a time were sending multiple packets at once will get merged into 1 when being received.
Ben's suggestion is right: With two connections, one will not be significantly blocked due to traffic on the other. With just one, the short message will not be received until the long one is.
Steven Sudit
send calls will never be merged; one call to recv will only read as much as was sent with one call to send.
brone
@brone: I've seen what nos explains in action. What is sent is both merged with other `send` s and split into several `recv` s
Default
@brone: `send` calls definitely can be merged, it's called Nagle's algorithm. http://en.wikipedia.org/wiki/Nagles_algorithm
Ben Voigt
@high6: Michael suggested a reasonable way to make this stream protocol work a bit more like one that respects packets, but you could also use UDP instead of TCP. Even then, things can happen en-route.
Steven Sudit
@brone, you are wrong, TCP does not preserve write/send boundaries. TCP provides a byte stream, not packets/messages.
nos
@nos: Do you have an example of this happening? Cause I tried sending a ton of 1 byte packets and it still received them 1 at a time even when the buffer was large enough to fit them all.
My evidence was http://msdn.microsoft.com/en-us/library/ms740121(VS.85).aspx -- see comment for the MSG_PEEK flag, though it's not exactly a model of clarity. I was under the impression this was standard SOCK_STREAM behaviour, and not some Winsock thing, because it's potentially useful, but http://www.opengroup.org/onlinepubs/009695399/functions/recv.html suggests not. (The docs imply that send may not send all of the data anyway, though maybe that's only for non-blocking sockets -- that's probably why.)
brone
Multiple send() calls CAN be merged together into larger transmission blocks (Nagle), it MAY take multiple send() calls to send a large amount of data, and it CAN take multiple recv() calls to read a single block of data. You definately DO need an application-level protocol in your data to detect the boundaries between messages (which are an appliation-level concept anyway, not a socket concept - at least for TCP). I have also seen this in action many times before. Most major socket libraries I have seen are coded to account for both conditions, because they DO happen.
Remy Lebeau - TeamB
A: 

I am not sure what we would acheive with this.. Mixing traffic on TCP stream won't server any purpose.. Can you explain what exactly u need to do.. Above all, we can never be sure in TCP that the other application has actually received the pkt (it might just be in their tcp buffers)...

Krishna
+2  A: 

Just use two separate TCP connections. They can even connect to the same host and port, the port number at your end will be different.

Stop-and-wait handshaking over any network (i.e. not loopback) would be miserably slow.

Ben Voigt
+1 for pointing out the two-connection solution.
Steven Sudit
or maybe _n_ separate connections.. :) +1 for multiple connections however
Default
+1  A: 

You could send the size of your packages instead

struct MyNetworkPackage {
    int size;
    char* data;
};

if you begin by sending the size, you can deduce on the other side what data belongs to what package.
I've tried to explain winsock in this answer as well.

Default
A: 

It seems that 'send' will block if there is a previous packet still being sent.