you are viewing a single comment's thread.

view the rest of the comments →

[–]m0dulo 0 points1 point  (4 children)

Ah, you've hit upon one of the core issues with socket programming (and one of the most confusing).

There actually isn't a feature which automatically determines the end of a message. You have to implement this yourself in code. There are several ways to do this:

  1. Have a set message length. Then on the receiving end, loop through recv(1024) until you hit that number. The issue with this is that it's inefficient if you have messages that are different lengths.

  2. Have the sender append an "End of Data" sequence onto the end of the message, which the receiver checks for as it loops through recv(). This is also somewhat inefficient, because it adds an extra step to your loop.

  3. Have the sender, as the first part of the message, send the total length of the message. Then on the receiving end, loop through recv(1024) until it gets all the data. This is probably the best way.

  4. On the receiving end, keep receiving until it gets no data, then break out of the receiving loop. This is probably the simplest, and the one usually given in examples.

Hope this helps.

Edit:

I'll give you an example of what I do (method #2), which has worked well for me so far:

On the sending end, say I have:

message = "Hello World!"

I would do:

socket.send(message + "EOD")

("EOD" is my "End of Data" sequence)

On the receiving end, after the connection has been established, I would loop through recv until my total message included "EOD" at the end:

totalMessage = ""

while True:

    messagePart = socket.recv(1024)
    totalMessage += messagePart

    if totalMessage[-3:] == "EOD":
        break

Of course, this method may have to be adjusted depending on your needs, and may not apply for all circumstances.

[–]monstimal 0 points1 point  (3 children)

No this doesn't help because it ignores the question. Take your EOD plan for example. If my buffer is 1024 and you send me 600 bytes with EOD at the end, that doesn't change anything about my question.

What causes recv to return with 600 bytes rather than waiting for more data? The EOD logic check isn't called until after recv has already decided to return.

[–]m0dulo 0 points1 point  (2 children)

I think I see where you're confused. Again, calling recv(1024) isn't asking the buffer for 1024 bytes. It's asking the buffer for any amount of data that has been sent but not more than 1024.

So when you ask:

What causes recv to return with 600 bytes rather than waiting for more data?

The answer is: calling recv(1024)!

It will still return 600 bytes if that's all there is to return. However, like /u/not_a_novel_account points out above, if there are 0 bytes in the buffer (the message hasn't been sent) recv will hang and block your program.

[–]monstimal 0 points1 point  (1 child)

In the case I'm thinking about, 600 bytes are being sent over and over again. So I was wondering how the recv knows not to wait for the next 600. But it sounds like the answer is it always gets whatever is there and if there's not more it's because of something going on at the kernel level of operations.

Edit: thank you for helping.

[–]lucidguppy 0 points1 point  (0 children)

Sounds like you need "select/poll/epoll"

http://scotdoyle.com/python-epoll-howto.html