MFC Sockets - File Transfer

Posted on 2003-03-05
Medium Priority
Last Modified: 2008-01-16

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!
Question by:birdgenj
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
LVL 49

Expert Comment

ID: 8078624
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
LVL 12

Accepted Solution

Salte earned 200 total points
ID: 8078784
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.


Author Comment

ID: 8080288
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!
LVL 12

Expert Comment

ID: 8080695
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.

LVL 49

Expert Comment

ID: 8084044
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 );

     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

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
Suggested Courses

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question