Re: CAsyncSocket and Send

Tech-Archive recommends: Fix windows errors by optimizing your registry



Thanks for the advice. I'll try taking it apart.

"Michael K. O'Neill" wrote:

> "Vinoj" <Vinoj@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
> news:21D3AC8A-8AB8-4051-BF14-8ED32922E5DF@xxxxxxxxxxxxxxxx
> > I'm using TCP/IP. I'm also sending/receivingbinary data (file transfer).
> >
> > The sending side sends an 'f' char immediately before a file is sent.
> When
> > the 'f' is received, the receive file routine is called (which receives
> the
> > file name - 256 chars, the file size, and then the file data). After
> that,
> > occasionally there will be no more data (expected), however, sometimes
> there
> > more data on the socket. The receive file routine follows (adapted from
> Mike
> > O'Niell's CSocket file transfer tutorial). Thanks.
> >
> > Vinoj
>
> The code you posted does not execute an "asynchronous" file transfer.
> Rather, the code is ocmpletely synchronous, since it executes, seriatim,
> reception of file name, followed by size, followed by data; and it does not
> complete until all tasks are also complete.
>
> An asynchronous file transfer would perform a single call to Receive() in
> response to an FD_READ notification (i.e., inside your
> CAsyncSocket::OnReceive() override), and then exit after updating your state
> machine, to await again a new FD_READ notification. The serial tasks shown
> in your function (below) would be "cobbled together" after multiple calls to
> OnReceive(), based on logic in your state machine.
>
> The various calls to Sleep() were probably needed to make the code "work",
> in the sense that a file was successfully received without a
> WSAGetLastError() of WSAEWOULDBLOCK. This alone should be enough to
> demonstrate to you that the code is not asynchronous, but rather very
> synchronous and sequential.
>
> As for "garbage being sent after data", if you are using
> http://www.codeproject.com/internet/SocketFileTransfer.asp , then nothing at
> all is being sent after the data, since the sending code specifically sends
> less than a full buffer at the end of a file (it only sends the final part
> of the file, which usually is less than a full buffer). On the receiving
> side, at the end of the file, the code is designed to write to the output
> file only the number of bytes remaining in the file, and not the entire
> buffer (i.e., the code writes to the file based on iiRecd (which is the
> number of bytes received) and not based on RECV_BUFFER_SIZE (which is the
> size of the buffer)).
>
> So, the only source of this behavior is if you are sending multiple files,
> and you do not correctly handle the point of demarcation between sending of
> the current file and that of a prior file.
>
> See specific notes on your code, below.
>
> Mike
>
>
> >
> > BOOL AsyncReceiveFile(CString FilePath){
> >
> > BOOL bRet = TRUE; // return value
> > int dataLength, cbBytesRet, cbLeftToReceive, loop = 0;
> > BYTE* recdData = NULL;
> >
> > CFile destFile;
> > char buff[256];
> > BOOL bFileIsOpen = FALSE;
> > Sleep(200);
> > CString strFileName;
> >
> > //receive the filename
> > memset(buff, 0, sizeof(buff));
> > cbLeftToReceive = MAX_FILENAME_LENGTH;
> > do{
> > cbBytesRet = pAsyncClient->Receive(buff, cbLeftToReceive, 0);
>
>
> This code is wrong, since it always loads the most-recently-received part of
> the file name to the beginning of the buffer. It should be something like
> this:
>
> cbBytesRet = pAsyncClient->Receive(buff+MAX_FILENAME_LENGTH-cbLeftToReceive,
> cbLeftToReceive, 0);
>
>
>
> > if(cbBytesRet > 0)
> > cbLeftToReceive -= cbBytesRet;
> > else if(++loop > 1000)
> > return FALSE;
> > }
> > while(cbLeftToReceive >0);
>
>
> This test makes sense only if the file name is always exactly
> MAX_FILENAME_LENGTH in length, and only if both sides agree on the value of
> MAX_FILENAME_LENGTH. As a better alternative, why not prefix the file name
> with the byte-count of the nae itself, much like you do when sending the
> file's data.
>
>
>
> >
> > strFileName = buff;
> > // open/create target file that receives the transferred data
> >
> > if(!(bFileIsOpen = destFile.Open((LPCTSTR)strFileName,
> > CFile::modeCreate|CFile::modeWrite|CFile::typeBinary))){
> > MessageBeep(MB_ICONEXCLAMATION);
> >
> > // Open Error Log File and Record Problem
> > }
> > return FALSE;
> > }
> >
> > // get the file's size
> > Sleep(200);
> > cbLeftToReceive = sizeof(dataLength);
> > loop = 0;
> >
> > do{
> > BYTE* bp = (BYTE*)(&dataLength) + sizeof(dataLength) -
> > cbLeftToReceive;
> > cbBytesRet = pAsyncClient->Receive( bp, cbLeftToReceive );
> >
> > // test for errors and get out if they occurred
> > if(cbBytesRet == SOCKET_ERROR || cbBytesRet == 0){
> > int iErr = ::GetLastError();
> > if(iErr != WSAEWOULDBLOCK){
> >
> > MessageBeep(MB_ICONEXCLAMATION);
> >
> > // Open Error Log File and Record Problem }
> >
> > return FALSE;
> > }
> > cbLeftToReceive += cbBytesRet;
> >
> > //if data cannot be read
> > if(++loop > 1000)
> > return FALSE;
> > }
> >
> > cbLeftToReceive -= cbBytesRet;
> >
> >
> >
> > }
> > while (cbLeftToReceive > 0);
> >
> > if((dataLength = ntohl( dataLength )) < 0){
> > MessageBeep(MB_ICONEXCLAMATION);
> >
> > // Open Error Log File and Record Problem
> > }
> > return FALSE;
> > }
> >
> >
> > // now get the file in RECV_BUFFER_SIZE chunks at a time
> > Sleep(200);
> > recdData = new byte[BUFFER_SIZE];
> > cbLeftToReceive = dataLength;
> > loop = 0;
> > do{
> > int iiGet, iiRecd;
> >
> > iiGet = (cbLeftToReceive<BUFFER_SIZE)?cbLeftToReceive:BUFFER_SIZE
> ;
> > iiRecd = pAsyncClient->Receive( recdData, iiGet );
> >
> > // test for errors and get out if they occurred
> > if (iiRecd == SOCKET_ERROR || iiRecd == 0){
> > int iErr = ::GetLastError();
> > if(iErr != WSAEWOULDBLOCK){
> > //Record error
> >
> > delete [] recdData;
> > return FALSE;
> > }
> > cbLeftToReceive += iiRecd;
> >
> > if(++loop > 1000)
> > return FALSE;
> > }
> >
> > // good data was retrieved, so accumulate
> > // it with already-received data
> > if(iiRecd > 0)
> > destFile.Write( recdData, iiRecd); // Write it
> > cbLeftToReceive -= iiRecd;
> >
> >
> > }
> > while ( cbLeftToReceive > 0 );
> >
> >
> > delete[] recdData;
> >
> > if ( bFileIsOpen )
> > destFile.Close();
> >
> > return bRet;
> > }
> >
> > "Joseph M. Newcomer" wrote:
> >
> > > Are you using TCP/IP or UDP?
> > >
> > > Are you making sure that, if you are handling strings, that you insert a
> terminating NUL
> > > character after the characters received? For example, if you have a 1K
> buffer, receive 4
> > > bytes representing 4 8-bit characters, then you must put a NUL in [4] a
> NUL character, or
> > > whatever is seen there will be seen as part of the string.
> > > joe
> > >
> > > On Tue, 10 Jan 2006 16:03:02 -0800, "Vinoj"
> <Vinoj@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote:
> > >
> > > >Hello,
> > > >
> > > >I have two programs that use async sockets. Occasionally, there is
> garbage
> > > >(extra bytes) being sent after data, thus confusing my finite state
> machine.
> > > >Is there a way to track everytime the send() is called? Any ideas on
> why
> > > >this could be happening?
> > > >
> > > >I don't know if it matters, but the sending side of the program is
> written
> > > >in C and the receiving side is MFC. Thanks.
> > > >
> > > >Vinoj
> > > Joseph M. Newcomer [MVP]
> > > email: newcomer@xxxxxxxxxxxx
> > > Web: http://www.flounder.com
> > > MVP Tips: http://www.flounder.com/mvp_tips.htm
> > >
>
>
>
.



Relevant Pages

  • Re: CAsyncSocket and Send
    ... I'm also sending/receivingbinary data (file transfer). ... which usually is less than a full buffer). ... >> Are you using TCP/IP or UDP? ... >>>in C and the receiving side is MFC. ...
    (microsoft.public.vc.mfc)
  • Re: pushing the envelope with sockets
    ... receiving on the socket they are received (upto the buffer size), you can even change what happens if the buffer runs full. ... int read = S.EndReceive; ... class AsyncReader: Reader ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Fundamentals question, is this how it works?
    ... Note the packet may be partially received when you get ... That is what i thought i was saying that it receives it all in a stream ... receving the buffer size each time. ... receiving that many bytes i then break and wait for the next set of data ...
    (microsoft.public.win32.programmer.networks)
  • Re: Fundamentals question, is this how it works?
    ... processing packets after you are done with one. ... receving the buffer size each time. ... TCP is a stream-based protocol, which means that it ignores any attempt ... then the receiving side might get ...
    (microsoft.public.win32.programmer.networks)
  • Re: pushing the envelope with sockets
    ... so it would seem 2.0 does indeed buffer UDP. ... Using async I/O ... receiving on the socket they are received, ... Okay, so during *one* run, the cpu spent increases when input-data is ...
    (microsoft.public.dotnet.languages.csharp)