Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 590
  • Last Modified:

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!
0
birdgenj
Asked:
birdgenj
  • 2
  • 2
1 Solution
 
DanRollinsCommented:
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
0
 
SalteCommented:
Another thing you can do is to recognize that this is a windows program and so the socket transfer should be detached from the main program loop.

There are two ways to do this:

1. Create a thread and let the connection use that thread. This is not necessarily the best way to go but it is sort of easy to understand - if you understand threads - and you use sockets in a more system independent way than the method two below.

2. Make the sockets 'windows aware'. The WinSock sockets can be made windows aware in such a way that you don't wait and receive packets from the socket. Instead you just run your program and tell the socket "send me a windows message if you get a packet". That way, whenever the socket receive a packet from the other machine it will send you a window message and you can handle that message the same way you handle resizing the window, pressing a button or menu or other event that might happen while running the windows program.

When you then get the message you can safely do a receive since the data is already there and there will be no waiting for data.

Tell me which way you want to go and I can try to dig up more info about either threads or the windows aware sockets.

Essentially they are the same in that a second thread would just wait for packets and when a packet came it would send the main thread a message. The window aware method is basically just having windows doing that message sending instead of yourself.

There is ONE more way but that is really hairy and since the other two methods should work fine there's no reason to do it. That would be to more or less replace the regular windows message loop with your own loop that wait for multiple objects and specify both the message queue and the socket as objects to wait for. When you then return from that wait you check if it returned because a message arrived you handle it and if it returned because the socket received a packet you handle that too.

It is really lots of work for absolutely no gain so I won't recommend that third method.

Alf
0
 
birdgenjAuthor Commented:
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!
0
 
SalteCommented:
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
0
 
DanRollinsCommented:
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
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now