Re: Socket Blocking Trouble!
Quote:
Originally posted by LearningMan
after a while, the amount of data sent will be -1 because send() returns -1.
How do I get past this? Am I even using blocking sockets? How do I implement a blocking socket?
It seems like you're using asynchronous sockets. The second code snippet you posted intercepts an FD_READ message and manipulates sckTransfer, so I'm guessing sckTransfer has been set up to notify on (at least) FD_READ's.
Now, you pose a couple of different problems:
1) send() does not naturally return SOCKET_ERROR (-1). One possible cause of an error whilst writing to an asynchronous socket is simply filling the network buffer. Any additional writes would force the socket to wait until some of the queued outgoing data has been successfully sent before writing whatever data you passed to the buffer. Since you're using asynchronous sockets (which are designed to return immediately), send() refuses to block and returns SOCKET_ERROR. A subsequent call to WSAGetLastError() would reveal WSAEWOULDBLOCK, meaning that you should wait before attempting to write to the socket again. I'm suggesting this as the most probable cause because you're running a very tight loop of read-from-file and write-to-socket with no waiting between intervals, which might be prone to overloading your outgoing buffer. However, you need to do some error checking to see if this is really the case.
If so, you'll need to process the FD_WRITE message and setup the socket to notify your window proc when space in the buffer becomes available once again, if you haven't already. Within your FD_WRITE code block, you'll need to read from the file, write to the socket, and check the return value of send(). If it returns SOCKET_ERROR, check the return value of WSAGetLastError(). If that returns WSAEWOULDBLOCK, exit your FD_WRITE code; the socket will tell you when the socket is again available for writing. It's also not a good idea to attempt sending the entire file when the user clicks the button since the entire program will stop to handle the networking task.
2) Asynchronous sockets might be the better choice in this case since you can concentrate on integration into your GUI code rather than write a separate class or full-blown transfer function and make it run in its own dedicated thread. However, you're trading the simplicity of blocking sockets for the power and difficulty of async sockets.
3) Your FD_READ processing seems a bit off. You'll want to check the return value of read() to make sure you're not getting SOCKET_ERROR's or WSAEWOULDBLOCK's. I'm assuming the sender somehow tells the receiver the size of the MP3 as it appears the receiver blindly intercepts data until FD_READ's simply are no longer sent. You can pull the transfer off without notifying the receiver of the file size by noting that recv() returns zero on a "graceful" shutdown, that is, the sender has called shutdown() on the socket--the HTTP protocol works on this principle.