Thread: Socket Blocking Trouble!

  1. #1
    LearningMan
    Guest

    Socket Blocking Trouble!

    I am in the process of making a program to send large files.

    This is a Win32 program.

    As you can see from my code, when the user clicks the send button, it starts the sending loop, which sends 1kb at a time.
    A log file is also opened and written to with the following details:
    the amount of data read from the file, and the amout of data sent.

    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?

    [IMPORTANT - READ]
    I realize there could be more data left over to send at the end of the sending loop. That problem is solved with a simple modulous calculation. This is not my problem.

    I know sending 1kb at a time is probably not the best. But I know you CAN send 1kb at a time, and this is what I want to do at the moment (I'm learning sockets).
    [/IMPORTANT - READ]

    Thank you for your replies.

    Here is my sending code (executes when a button on the form is clicked)

    Code:
    			case IDC_CLICK_SEND:
    				{
    					FILE *fRD = NULL;
    					long fLength = -1;
    					char chrRead[1024] = {0};
    					char outputlog[256];
    					int actualRead, actualSent;
    
    					FILE *LOG = fopen("c:\\documents and settings\\kj\\desktop\\log.txt", "w");
    
    					if((fRD = fopen("c:\\documents and settings\\kj\\desktop\\Ballad.mp3", "rb")) == NULL)
    					{
    						MessageBox(hWnd, "fopen failed.", "error", MB_OK);
    						return 0;
    					}
    
    					fLength = retFileLength(fRD);
    
    					for(int x = 0; x < (fLength / 1024); x++)
    					{
    						if(!fseek(fRD, (x * 1024), SEEK_SET))
    						{
    							actualRead = fread(chrRead, sizeof(char), 1024, fRD);
    							actualSent = send(sckTransfer, chrRead, 1024, 0);
    							sprintf(outputlog, "Actual Read: %d; Actual Sent: %d.\n", actualRead, actualSent);
    							fwrite(outputlog, sizeof(char), strlen(outputlog), LOG);
    						}
    					}
    
    					MessageBox(hWnd, "Done Sending", "", MB_OK);
    					closesocket(sckListen);
    					closesocket(sckTransfer);
    					fclose(fRD);
    					fclose(LOG);
    
    					return TRUE;
    				}
    Here is my receiving code (executes when FD_READ message is received (WSAAsyncSelect)):

    Code:
    			case FD_READ:
    				{
    					char chrRead[1024] = {0};
    					int actualReceived = 0;
    
    					actualReceived = recv(sckTransfer, chrRead, sizeof(chrRead), 0);
    					fwrite(chrRead, sizeof(char), actualReceived, fWR);
    
    					return TRUE;
    				}

  2. #2
    LearningMan1
    Guest
    Oh btw, send will return -1 BEFORE the file is completely sent. Sorry I didn't get that in last time. OOPS!

  3. #3
    Registered User johnnie2's Avatar
    Join Date
    Aug 2001
    Posts
    186

    Re: Socket Blocking Trouble!

    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.
    "Optimal decisions, once made, do not need to be changed." - Robert Sedgewick, Algorithms in C

  4. #4
    LearningMan
    Guest
    thanks!

    -learningman

  5. #5
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    this stuff sounds interesting. are there any good tutorials about sockets and communication, etc?
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  6. #6
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Originally posted by bennyandthejets
    this stuff sounds interesting. are there any good tutorials about sockets and communication, etc?
    Many links have been posted before. Here's one .
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  7. #7
    Registered User johnnie2's Avatar
    Join Date
    Aug 2001
    Posts
    186
    That's quite a links page, but it's missed out on a couple worthy tutorials. You'll also want to look at Warren Young's Winsock Programmer's FAQ (on the list but deserving of more recognition), Dan Royer's flipCode.com networking column, and Johnnie's Winsock Tutorial.
    "Optimal decisions, once made, do not need to be changed." - Robert Sedgewick, Algorithms in C

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. EAGAIN with write on a non blocking socket
    By mynickmynick in forum Networking/Device Communication
    Replies: 0
    Last Post: 04-30-2009, 09:59 AM
  2. how to intilise a non blocking socket?
    By lolguy in forum Networking/Device Communication
    Replies: 7
    Last Post: 03-20-2009, 12:18 AM
  3. How to initialize a non blocking socket using only winsock library
    By *DEAD* in forum Networking/Device Communication
    Replies: 4
    Last Post: 01-18-2008, 07:03 AM
  4. SOcket programming trouble
    By sodja in forum Networking/Device Communication
    Replies: 1
    Last Post: 01-11-2008, 10:20 AM
  5. Odd socket trouble
    By Twiggy in forum C Programming
    Replies: 0
    Last Post: 03-31-2003, 05:25 PM