🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.internet.socket
3 messages
3 total messages Started by maxch Mon, 05 Jul 2004 15:57
BCB6 bug ?
#5670
Author: maxch
Date: Mon, 05 Jul 2004 15:57
743 lines
19407 bytes
Hi All,
I have a very very strange question on C++Builder6, maybe it should
be posted on Compiler group, however, the problem is encountered when I
compile a SOCKET program which download from
http://support.microsoft.com/default.aspx?scid=kb;en-us;193066 EchoC
which I just have changed some lines of the code.

Please see following for the code.
The symptom is
if I commented the line marked with **************
    the program terminated successfully
else
    the program goes to line marked with @@@@@@@@ and infinitely
    invoke that function, at last, a unkown software exception pop up.

I never encounted this problem before, whether it's a compiler bug?

Computer info:
Win2K prof, with SP4
C++BUILDER 6 with SP4


code:

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%% the following is echoc.h

#ifndef _OVERLAPPEDECHOCLIENT
#define _OVERLAPPEDECHOCLIENT

#define MAX_CHAR_LINE 1024

VOID
dbgprintf(
 const PCHAR lpszFmt,
 ...)
/*++
Routine Description:

 Use this function for printf-style debugging output.

Arguments:

 lpszFmt - format string

Return Value:

    None.
--*/
{
 CHAR szBuf[512];
 va_list vargs;

 va_start(vargs, lpszFmt);
 vsprintf(szBuf, lpszFmt, vargs);
 va_end(vargs);
 OutputDebugString(szBuf);
 return;
} // dbgprintf


//
// Console control handler, intercept Ctrl+C and Ctrl+Brk
//

BOOL WINAPI
CtrlHandler (
 DWORD dwEvent
 );

WSAEVENT gheventAsynRecv = NULL;
WSAEVENT gheventAsynSend = NULL;
WSAEVENT gheventOlSock = NULL;

//
// echo client socket
//

SOCKET  gsClientSock = INVALID_SOCKET;

//
// Default is overlapped I/O without notifications.
//

BOOL bCompletionFunction = TRUE;

//
// If user hits Ctrl+C, gbEndClient is set to TRUE
//

BOOL gbEndClient = FALSE;

DWORD gbytesRecvd = 0;

//
// Socket state is closed
//

BOOL gbSocketClosed = FALSE;

#endif //_OVERLAPPEDECHOCLIENT


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%% the following is echoc.cpp

// olechoc.cpp
//
// Copyright (c)1998 Microsoft Corporation, All Right Reserved
//
// Module description:
//
//  The program demonstrates overlapped socket I/O with or without
completion
//  callback functions. It reads from console input, sends the input to the
echo
//  server, and displays the echo.
//     Then it loops back to read again and continue the cycle in an endless
loop.
//  The endless loop will only break when users hit CTRL+C or
//  CTRL+Brk.
//
//
//

#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include "echoc.h"



void CALLBACK
AysncSendCompletion(
 DWORD dwError,
 DWORD cbTransferred,
 LPWSAOVERLAPPED lpOverlapped,
 DWORD dwFlags
 )
/*++
Routine Description:

 Aysnc Send Completion Routine

Return Value:

    None.
--*/
{
 dbgprintf("AysncSendCompletion dwError is %d \n", dwError); //
@@@@@@@@@@@@@@@@@@@@
 dbgprintf("AysncSendCompletion cbTransferred is %d \n", cbTransferred);
 dbgprintf("AysncSendCompletion dwFlags is %d \n", dwFlags);

 //
 // The other side closed socket, setting gbSocketClosed to TRUE so that
 // main thread can bail out and close the socket.
 //

 if (dwError == 0 && cbTransferred == 0) gbSocketClosed = TRUE;

 //
 // if not ERROR_IO_INCOMPLETE, then error occurs and we set
 // gbSocketClosed to TRUE so that
 // main thread can bail out and close the socket.
 //

 if (dwError !=0 && dwError != 996) gbSocketClosed = TRUE;

 //
 // Signal the event so that main thread wait unblocks.
 //

 WSASetEvent( gheventAsynSend);

} // AysncSendCompletion



void CALLBACK
AysncRecvCompletion(
 DWORD dwError,
 DWORD cbTransferred,
 LPWSAOVERLAPPED lpOverlapped,
 DWORD dwFlags)
/*++
Routine Description:

 Aysnc Recv Completion Routine

Return Value:

    None.
--*/
{
 dbgprintf("AysncRecvCompletion dwError is %d \n", dwError);
 dbgprintf("AysncRecvCompletion cbTransferred is %d \n", cbTransferred);
 dbgprintf("AysncRecvCompletion dwFlags is %d \n", dwFlags);

 gbytesRecvd = cbTransferred;

 //
 // The other side closed socket, setting gbSocketClosed to TRUE so that
 // main thread can bail out and close the socket.
 //

 if (dwError == 0 && cbTransferred == 0) gbSocketClosed = TRUE;


 //
 // if not ERROR_IO_INCOMPLETE, then error occurs and we set
 // gbSocketClosed to TRUE so that
 // main thread can bail out and close the socket.
 //

 if (dwError !=0 && dwError != 996) gbSocketClosed = TRUE;

 //
 // Signal the event so that main thread wait unblocks.
 //

 WSASetEvent( gheventAsynRecv);

} // AysncRecvCompletion



void main(int argc, char *argv[])
/*++

Routine Description:

 Process main. It first sets up a console control handler so that we can
intercetp
 CTRL+C or CTRL+Brk to shut down echo client and clean up resources. It then
 initiates winsock runtime, and depends the command line bCompletionFunction
to
 determine whether to use a completion routine with the socket overlapped
i/o.

Arguments:

 int argc,
 char *argv[]

Return Value:

    None.

--*/
{
 TCHAR  strSendData[MAX_CHAR_LINE]; // Send line buffer
 TCHAR  strRecvData[MAX_CHAR_LINE]; // Read line buffer
 WSABUF  buffSend;   // WSABuf for WSASend
 WSABUF  buffRecv;   // WSABuf for WSARecv

 TCHAR  strHostEntry[256];
 unsigned short  nPortID;

 int   nWSAError;
 WSADATA  wsaData;
 SOCKADDR_IN addrInet;


 WSAOVERLAPPED olSend;   // OL structure for send
 WSAOVERLAPPED olRecv;   // OL structure for recv
 WSAEVENT  eventArray[2];

 DWORD  dwNumBytes;
 DWORD  dwFlags;
 DWORD  dwRet, i;
 int   nZero = 0;
 int   ch;
 BOOL  bReadAll = FALSE;
 BOOL  bSendAll = FALSE;
 int   nSendSize = 0;

 if (argc != 4) {

  printf("Usage: echoc.exe <server> <port> <completion routine(0 or 1)>\n");
  return;
 }

 if (atoi(argv[3]) == 0) {
    bCompletionFunction = FALSE;
  }
 else {
    bCompletionFunction = TRUE;
  }

 lstrcpy(strHostEntry, argv[1]);
 nPortID = (unsigned short) atoi(argv[2]);

 try {
    try {

      if (!SetConsoleCtrlHandler (
            CtrlHandler,  //Console Control Handler
            TRUE    //Install Console Handler
            )) {
        printf ("SetConsoleCtrlHandler failed to install console handler:
%d\n",GetLastError());
        return;
        //__leave;
      }

      if ((gheventAsynRecv = WSACreateEvent()) == WSA_INVALID_EVENT) {
        printf("WSACreateEvent failed: %d\n", WSAGetLastError());
        dbgprintf("WSACreateEvent failed: %d\n", WSAGetLastError());
        return;//__leave;
      }

      if ((gheventAsynSend = WSACreateEvent()) == WSA_INVALID_EVENT) {
        printf("WSACreateEvent failed: %d\n", WSAGetLastError());
        dbgprintf("WSACreateEvent failed: %d\n", WSAGetLastError());
        return; //__leave;
      }

      if ((gheventOlSock = WSACreateEvent()) == WSA_INVALID_EVENT) {
        printf("WSACreateEvent failed: %d\n", WSAGetLastError());
        dbgprintf("WSACreateEvent failed: %d\n", WSAGetLastError());
        return; //__leave;
      }

      ZeroMemory(&olSend, sizeof(WSAOVERLAPPED));
      ZeroMemory(&olRecv, sizeof(WSAOVERLAPPED));

      if (  WSAStartup(0x202,    //Request Winsock 2.02
                        &wsaData
        ) == SOCKET_ERROR) {

        dbgprintf("WSAStartup failed with error %d\n",WSAGetLastError());
        return; //__leave;
      }

      if ((gsClientSock = WSASocket(
          AF_INET,   // address family
          SOCK_STREAM,  // socket type
          IPPROTO_IP,   // protocol
          NULL,    // pointer to a WSAPROTOCOL_INFO structure
          0,     // reserved for future use with socket groups
          WSA_FLAG_OVERLAPPED // socket attribute required for IOCP;
          )) == INVALID_SOCKET)  {

        throw "asdflkj";
        dbgprintf("Failed to get a socket %d\n", WSAGetLastError());
        return; //__leave;
      }

      if ((addrInet.sin_addr.s_addr = inet_addr(strHostEntry)) ==
INADDR_NONE) {
        printf("*** inaddress none\n");

        LPHOSTENT lphostent;
        if ((lphostent = gethostbyname(strHostEntry)) != NULL) {
          printf("*** get ip ok by name\n");
          addrInet.sin_addr.s_addr = ((LPIN_ADDR)
(lphostent->h_addr_list[0]))->s_addr;
        }
        else {
          printf("*** get ip error by name %s.\n", strHostEntry);
          dbgprintf("Failed to gethostbyname %d\n", WSAGetLastError());
//**************
          return; //__leave;
        }
      }

      printf("here ...\n");
      addrInet.sin_family = AF_INET;
      addrInet.sin_port = htons(nPortID);

      printf("start to connecting servier....\n");
      if (WSAConnect(
          gsClientSock,
          (PSOCKADDR) &addrInet,
          sizeof(addrInet),
          NULL,
          NULL,
          NULL,
          NULL
          ) == SOCKET_ERROR) {

        dbgprintf("Failed to connect a socket %d\n", WSAGetLastError());
        return; //__leave;
      }
      printf("connection ok\n");
      gbSocketClosed = FALSE;

      //
      // Disable send buffering on the socket.  Setting SO_SNDBUF
      // to 0 causes winsock to stop bufferring sends and perform
      // sends directly from our buffers, thereby reducing CPU
      // usage.
      //

      nZero = 0;
      if ( setsockopt(
          gsClientSock,
          SOL_SOCKET,
          SO_SNDBUF,
          (char *)&nZero,
          sizeof(nZero)
          ) == SOCKET_ERROR) {
        dbgprintf("setsockopt failed to set SO_SNDBUF %d\n",
WSAGetLastError());
        return; //__leave;
      }

      while (!gbEndClient) {

        buffSend.buf = strSendData;
        buffSend.len = 0;
        printf( "Enter a line: " );   /* Read in single line from "stdin":
*/

        for( i = 0; (i < MAX_CHAR_LINE) &&  ((ch = getchar()) != EOF)
                && (ch != '\n'); i++ )
          buffSend.buf[i] = (char)ch;
        /* Terminate string with null character: */
        buffSend.buf[i] = '\n';
        buffSend.buf[i+1] = '\0';

        buffSend.len = i+1;


        eventArray[0] = gheventOlSock;
        nSendSize = buffSend.len;
        //
        // if a completion function is used, we don't need an event handle
        // in the overlapped structure.
        //

        if (!bCompletionFunction) olSend.hEvent= gheventOlSock;

        bSendAll = FALSE;
        while (TRUE)  //we will send in a loop until nSendSize bytes are
sent
        {
          if ((dwRet = WSASend(
            gsClientSock,
            &buffSend,
            1,
            &dwNumBytes,
            0,
            &olSend,
            bCompletionFunction? AysncSendCompletion : NULL)
            ) == SOCKET_ERROR) {

            nWSAError= WSAGetLastError();

            if (nWSAError != ERROR_IO_PENDING) {

              dbgprintf("WSASend failed with error %d\n", nWSAError);
              return; //__leave;
            }
            else {
              //ERROR_IO_PENDING is expected.
            }
          }
          else {

            dbgprintf("WSASend sends data out immediately: %d bytes sent\n",
dwNumBytes);
          }

          //
          //  eventArray contains gheventOlSock.
          //  gheventOlSock is set in olSend only when no completion
function is used.
          //  When the overlapped send completes, gheventOlSock is going to
signal.
          //
          //  For overlapped send with completion function, gheventOlSock is
not set in
          //  olSend. So gheventOlSock is not going to signal, however the
last param
          //  of WSAWaitForMultipleEvents is going to put this thread into
an alertable
          //  wait state. When overlapped Send completes and completion
          //  function gets called, this Wait returns.
          //

          if (WSAWaitForMultipleEvents(
              1,
              eventArray,
              FALSE,
              WSA_INFINITE,
              bCompletionFunction
              ) == WSA_WAIT_FAILED) {

            dbgprintf("WSAWaitForMultipleEvents failed %d\n",
WSAGetLastError());
            return; //__leave;
          }

          //
          // Reset the gheventOlSock
          //

          WSAResetEvent(eventArray[0]);

          if (bCompletionFunction) {

            //
            // For overlapped send with completion routine, we will wait on
            // gheventAsynSend. The end of the AysncSendCompletion signals
            // the event
            //

            WSAWaitForMultipleEvents(
              1,
              &gheventAsynSend,
              TRUE,
              INFINITE,
              TRUE);
            WSAResetEvent(gheventAsynSend);
          }

          if (WSAGetOverlappedResult(
              gsClientSock,
              &olSend,
              &dwNumBytes,
              FALSE,
              &dwFlags
              ) == TRUE) {

            dbgprintf("%d bytes were sent\n", dwNumBytes);
          }
          else {

            dbgprintf("WSAGetOverlappedResult failed with error %d\n",
WSAGetLastError());
          }

          //
          // An overlapped write completes doesn't necessary mean all the
data to send are
          // sent.
          //

          buffSend.len -= dwNumBytes;
          if (buffSend.len == 0)
            break;
          else
            buffSend.buf += dwNumBytes;
        }

        dbgprintf ("send complete\n");

        //
        // Now we need to read the echo back.
        //

        //
        // if a completion function is used, we don't need an event handle
        // in the overlapped structure.
        //

        if (!bCompletionFunction) olRecv.hEvent = gheventOlSock;

        bReadAll = FALSE;
        while (TRUE)  //we will read until '\n' is received
        {

          buffRecv.buf = strRecvData;
          buffRecv.len = sizeof(strRecvData);
          ZeroMemory (buffRecv.buf, buffRecv.len);
          dwFlags = 0;
          dwNumBytes = 0;


          if ((dwRet =WSARecv(
              gsClientSock,
              &buffRecv,
              1,
              &dwNumBytes,
              &dwFlags,
              &olRecv,
              bCompletionFunction? AysncRecvCompletion : NULL
              )) == SOCKET_ERROR) {

            nWSAError = WSAGetLastError();

            if (nWSAError != ERROR_IO_PENDING)
            {
              dbgprintf("WSARecv failed with error %d\n", nWSAError);
              return; //__leave;
            }
          }
          else {

            dbgprintf("WSARecv returns immediately: %d bytes read\n",
dwNumBytes);
          }

        //
        //  eventArray contains gheventOlSock.
        //  gheventOlSock is set in olRecv only when no completion function
is used.
        //  When the overlapped recv completes, gheventOlSock is going to
signal.
        //
        //  For overlapped recv with completion function, gheventOlSock is
not set in
        //  olSend. So gheventOlSock is not going to signal, however the
last param of
        //  WSAWaitForMultipleEvents is going to put this thread into an
alertable wait state.
        //  When overlapped Recv completes and completion
        //  function gets called, this Wait returns.
        //
          if (WSAWaitForMultipleEvents(
              1,
              eventArray,
              FALSE,
              WSA_INFINITE,
              bCompletionFunction
              ) == WSA_WAIT_FAILED) {

            dbgprintf("WSAWaitForMultipleEvents failed %d\n",
WSAGetLastError());
            return; //__leave;
          }

          //
          // Reset the gheventOlSock
          //

          WSAResetEvent(eventArray[0]);

          if (bCompletionFunction) {

          //
          // For overlapped recv with completion routine, we will wait on
          // gheventAsynRecv. The end of the AysncSendCompletion signals
          // the event
          //
            WSAWaitForMultipleEvents(
              1,
              &gheventAsynRecv,
              TRUE,
              INFINITE,
              TRUE);
            WSAResetEvent(gheventAsynRecv);
          }

          if (!bCompletionFunction && WSAGetOverlappedResult(
                gsClientSock,
                &olRecv,
                &dwNumBytes,
                FALSE,
                &dwFlags
                ) == TRUE) {

            if (dwNumBytes == 0)
              break;

            gbytesRecvd = dwNumBytes;
            dbgprintf("%d bytes were received\n", dwNumBytes);
          }
          else {

            if (!bCompletionFunction) {

              dbgprintf("WSAGetOverlappedResult failed with error %d\n",
WSAGetLastError());
            }
          }
          if (gbSocketClosed) return; //__leave;

          printf(buffRecv.buf);

          nSendSize -= dwNumBytes;
          if (nSendSize == 0 ) break; // read all echo, break
        }
      }

    }
    catch (...) {
      printf("something error!!! \n");
    }
  }
 __finally {

  if (gheventAsynRecv) WSACloseEvent(gheventAsynRecv);
  if (gheventAsynSend) WSACloseEvent(gheventAsynSend);
  if (gheventOlSock)  WSACloseEvent(gheventOlSock);
  if (gsClientSock != INVALID_SOCKET) closesocket(gsClientSock);
  WSACleanup();
  SetConsoleCtrlHandler (CtrlHandler, FALSE);
 }

}// end main


BOOL WINAPI CtrlHandler (
 DWORD dwEvent
 )
/*++

Routine Description:

 Intecept CTRL+C or CTRL+Brk for the console.

Arguments:

 dwEvent - Console events

Return Value:

    None.

--*/
{
 switch (dwEvent) {

  case CTRL_C_EVENT:
  case CTRL_BREAK_EVENT:
  case CTRL_LOGOFF_EVENT:
  case CTRL_SHUTDOWN_EVENT:
  case CTRL_CLOSE_EVENT:

   gbEndClient = TRUE;

   if (gsClientSock) closesocket (gsClientSock);
   gsClientSock = INVALID_SOCKET;
   if (gheventAsynRecv) WSACloseEvent(gheventAsynRecv);
   gheventAsynRecv = NULL;
   if (gheventAsynSend) WSACloseEvent(gheventAsynSend);
   gheventAsynSend = NULL;
   if (gheventOlSock)  WSACloseEvent(gheventOlSock);
   gheventOlSock = NULL;
   WSACleanup();
   return (FALSE); //clean enough to exit the process now.

  default:
   // unknown type--better pass it on.
   return (FALSE);
  }
    // Handled all known events
 return (TRUE);
} //CtrlHandler
Re: BCB6 bug ?
#5671
Author: maxch
Date: Mon, 05 Jul 2004 16:14
17 lines
1377 bytes
I must say how I run that program

echoc asdf 10001 0
      ^^^^ yes, it's a host that cannot be reachable.

Thanks In Advance!


> Hi All,
> I have a very very strange question on C++Builder6, maybe it should
> be posted on Compiler group, however, the problem is encountered when I
> compile a SOCKET program which download from
> http://support.microsoft.com/default.aspx?scid=kb;en-us;193066 EchoC
> which I just have changed some lines of the code.
>
> Please see following for the code.
........
Re: BCB6 bug ?
#5693
Author: maxch
Date: Fri, 09 Jul 2004 13:30
13 lines
1235 bytes
Hi All,
Please ignore this question because the problem didnot happene
again after I commented the line
#define WIN32_LEAN_AND_MEAN

Regards,
chenzero

"maxch" <chenzero@netease.com> д���ʼ�
news:40e97ab1@newsgroups.borland.com...
> Hi All,
> I have a very very strange question on C++Builder6, maybe it
........
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads