Link to home
Start Free TrialLog in
Avatar of birdgenj
birdgenj

asked on

MFC Sockets - File Transfer

Hi,

I'm looking to build a program based on a MFC Dialog client program, and I want it to be able to connect to another computer also running the same program, and have the ability to send files. (messages also would be ideal, however files is the important part.)

I have tried a couple things, but the problem I usually run into is that the program stops responding when it is listening for connections.. waiting to receive data etc.

I don't know enough about threads to understand some of this...

Can anyone explain how to create a program that can do this & Explain how to avoid the problem that the program hangs while waiting?

Source code/examples would be appreciated.

Thanks in advance!
Avatar of DanRollins
DanRollins
Flag of United States of America image

The problem with sockets is that if you request to read more bytes that then remote party wants to send, it will wait there indefinately for more bytes (or until some low-level timeout occurs).

The trick is to alwyas send packets, with a header that indicates the length of the data.  For instance, if you intend to send 1000 bytes, then first send a four-byte value of 1000.  Then send the 1000 bytes.

That way, the recieving program doesn't get hung waiting for data that may or may not come.  When it accepts a connection, it simply waits for four bytes.  It reads them and sees that 1000 more bytes are on the way, so the next socket read requests exactly 1000 bytes!  It is never hung up waiting for more data unless the client actually dies midway though a transmission.

-- Dan
ASKER CERTIFIED SOLUTION
Avatar of Salte
Salte

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of birdgenj
birdgenj

ASKER

Salte (Alf)

From what I understand, making the sockets window's aware would be the better way to implement sockets into my program... i.e. I want it to start sending, and I want to be able to display transfer statistics.

If you have any links to doccumentation on threads, that'd be great, but otherwise if you could explain how to make the sockets 'windows aware' that would be great.

Thanks again!
You do that by a windows specific extension to the sockets. The function is defined in winsock.h but as it is a windows specific extension it has WSA... in front of the name.

I can't recall the exact name and I don't have windows here (I am sitting on a linux machine) but it should be easy enough to find when you search through the winsock documentation. It is a function that instructs the socket to send a window message to a specified window handle whenever a packet is available to read from the socket. It works for TCP, UDP and also for other sockets (raw sockets).

Just check out the WSA... functions and it has a window handle as an argument (the window handle that will receive the message), I don't think there are many socket functions that take window handles as arguments so I don't think there are many to choose from :-) The name will of course also suggest what the function is doing but I can't remember the specific name right now. I am not sure but I believe it is also possible to provide a parameter to indicate the message to send for notification of incoming packets.

Read the winsock documentation for details.

Alf
If you are using the MFC classes, look into CSocket.  It turns out to be trivially easy to connect then assigne a CSocketFile attached to a CArchive.  THis is a piece of a socekt app I wrote... not intended for you to cut-and-paste, only as an example...

     CSocketFile file( m_pcSocket );
     CArchive    arIn( &file, CArchive::load);
     
     int nActual;

   TRY {
     nActual= arIn.Read( buf, 5 ); // total msg len (including these 5 bytes)
   }
   CATCH_ALL ( e ) {
     LogPrintf( "ERROR reading ACE Hdr Pkt" );
     return( IS_ERR );
   }
   END_CATCH_ALL

     if ( nActual != 5 ) {
          sResp= CString( buf, nActual );
          LogPrintf( "Rx: Unexpected/Invalid  packet: '%s' ", (LPCSTR) sResp );
          return( IS_ERR );
     }

...
     //--------------------------- read the rest of the msg
     nActual= arIn.Read( pBuf, nAceMsgLen-5 );  

If you want to display some sort of progress gauge, you can make a loop to do the arIn.Read calls in smaller chunks and update the gauge inside the loop.

-- Dan