Hello everyone,
I was wondering what is the right way to use the send and recv functions?
Since the send function might not send all the data, should I use a loop to send it all? Or should I check the FD_WRITE message before doing so (by the way, what is this FD_WRITE message for and how do I use it?)?
What about the recv function? If I get the FD_READ message and use the recv function requesting 100 bytes and there is more than that available, will another FD_READ message be issued in order for me to request the remaining bytes? Or will it be lost if I don't request it?
I hope you can understand what I am asking. I don't think I did a good job of explaining.
Thanks in advance.
Posted on 2003-03-11 21:09:41 by dilau
I dont understand, what you mean with the FD_WRITE Message.

But you are right, if the FD_READ Message is posted and you use the recv-function and the buffer for the data is not big enough, the rest will be lost
Posted on 2003-03-12 07:32:01 by ChigpA
Originally posted by dilau
Hello everyone,
I was wondering what is the right way to use the send and recv functions?
Since the send function might not send all the data, should I use a loop to send it all?

Yes and no. From your post I see you're using WSAAsyncSelect, thus non-blocking sockets. If send succeeds and returns the number of bytes sent but that's less than what you needed to send, just send the part of the data that hasn't been sent again. If it still succeeds, loop. However, as soon as your send call fails, check the winsock error code. If it's WSAEWOULDBLOCK, an FD_WRITE message will be sent. Wait for this message, then do the above loop again to send the rest of the data. Do not wait for FD_WRITE if send succeeded, as it will not be sent then. If the error code is something else, something went wrong.

Or should I check the FD_WRITE message before doing so (by the way, what is this FD_WRITE message for and how do I use it?)?
What about the recv function? If I get the FD_READ message and use the recv function requesting 100 bytes and there is more than that available, will another FD_READ message be issued in order for me to request the remaining bytes? Or will it be lost if I don't request it?
I hope you can understand what I am asking. I don't think I did a good job of explaining.
Thanks in advance.

This information is all described in the WSAAsyncSelect docs, read the whole thing, it's really useful. Here's a piece of it:
[...]
Here is a summary of events and conditions for each asynchronous notification message.
FD_READ:
a. When WSAAsyncSelect is called, if there is data currently available to receive.
b. When data arrives, if FD_READ is not already posted.
c. After recv or recvfrom is called (with or without MSG_PEEK), if data is still available to receive.
Note: When setsockopt SO_OOBINLINE is enabled, data includes both normal data and OOB data in the instances noted above.

FD_WRITE:
a. When WSAAsyncSelect called, if a send or sendto is possible.
b. After connect or accept called, when connection established.
c. After send or sendto fail with WSAEWOULDBLOCK, when send or sendto are likely to succeed.
d. After bind on a connectionless socket. FD_WRITE may or may not occur at this time (implementation-dependent). In any case, a connectionless socket is always writeable immediately after a bind operation.
[...]


For a general overview of the way winsock I/O models work, have a look at the 5th chapter of my winsock tutor:
http://www.madwizard.org/view.php?page=tutorials.networking.chapter5&lang=asm
Its just an overview yet, but it might be helpful anyway.

Thomas
Posted on 2003-03-12 10:42:53 by Thomas

I dont understand, what you mean with the FD_WRITE Message.

But you are right, if the FD_READ Message is posted and you use the recv-function and the buffer for the data is not big enough, the rest will be lost

What do you mean by lost? It won't be lost in the sense that you won't receive it anymore. The remaining data will just stay in winsock's internal buffers until you receive it. If you get an FD_READ message when 10 bytes are available, and you recv with a buffer of 7 bytes, 3 bytes will remain in winsock's buffers, and winsock will immediately send an FD_READ message again because data is still available (see point c for FD_READ in the PSDK quote in my above post).

Thomas
Posted on 2003-03-12 10:45:25 by Thomas
Thank you very much, Thomas!
You answered all my questions. I love your tutorial! It is great! Thanks! I did not know you had a new chapter available. I was actually reading your tutorial before, while writing my program, and realized that the next chapter would be just what I needed, but I thought you had stopped updating it. Thanks for this tutorial. I am looking forward the next chapter.
Thank you again.
Posted on 2003-03-12 23:32:30 by dilau
Hey Thomas,
Can I ask for your opinion on how to implement the sending routine?
I got the reading routine working perfectly.
I thought about two ways for the sending routine. One is to have a buffer where I would append everything I wanna send. Then I would have a sending function that would check the buffer and send its contents if it is not empty. Then every time I get a FD_WRITE I just have to call the function. The problem would be the size of the buffer. I would be limited to that.
The other way I thought was creating a thread for the sending function and just looping until it sends everything. This would solve the buffer size problem, but like you said in your tutorial, it would waste precious CPU time.
Which one do you think is the best? Or can you give me a suggestion of other ways to do this?
Thank you very much again.
Posted on 2003-03-13 00:27:09 by dilau
What kind of program are you writing? Usually, protocols have a client-server model of communicating, i.e. the client requests something, the server responds. In that case, you could use the request of the client as a trigger to create the (full) response, and then loop on send as long as it succeeds, when it fails, set a flag that not everything was sent and continue on the next FD_WRITE message. The loop on send while it succceeds isn't inefficient, since the call will return immediately and most likely will fail the second time already (first time maximum is sent, second time you have to wait). Looping all the time without even using the FD_WRITE notification *is* CPU inefficient, but you already said that.
I can't tell you much more right now, it would really help if I knew the type of program.

Thomas
Posted on 2003-03-13 09:39:51 by Thomas
Hello Thomas,
Thanks again for your help.
I am writing a chat program just to learn how to use winsock functions. I don't need that much reliability with this kind of program, but I just wanna know the perfect way to use winsock. I want to learn to implement a fail-proof way.
Posted on 2003-03-13 10:32:43 by dilau
Winsock is reliable if you use TCP/IP, unless you use winsock in the wrong way (like assuming send will send all your data at once). For a chat program, when the user types a message and you want to send it, set a flag that a message has to be sent. Initiate the sending with a loop on send until it fails (WSAEWOULDBLOCK is okay, otherwise it's an error), then on the next FD_WRITE message, see if the flag is set and if it is, send the next bit of data and so on. When all data is sent, unset the flag.

Thomas
Posted on 2003-03-13 10:54:32 by Thomas
Thanks for your reply again, Thomas.
I'll try to do that. But I was wondering, what if I called the send function and it didn't send all the data, and while I am waiting for the FD_WRITE message, I have to send something else? How should I organize this? Should I use the buffer that I mentioned? The bad thing would be the buffer limit.
Posted on 2003-03-18 00:30:38 by dilau