Solved

Winsock16 Programming examples in Borland C++

Posted on 1997-05-31
1
651 Views
Last Modified: 2008-03-06
I'm looking for examples of Winsock programming (for Win16 preferred) in Borland C++. I'm interested in POP3 and SMTP mail usage or FTP programs.
0
Comment
Question by:beethoven
1 Comment
 
LVL 3

Accepted Solution

by:
gaohong earned 150 total points
Comment Utility
Hi, following is my stream socket used in my telnet session.
     You could use it strip down things from global.h and mxapp.h
     (e.g. define of uint, DLLCLASS, Message(), Telnet class ...)
 
     It bulds connection, and in my case ask telnet service.
     You should ask for SMTP service.

     It is used in BC++ for both 16bit and 32bit, just have right
     winsock.lib linked to your project

     good luck
     gaohong xie


     .h file


  /**************************************************************************
      * Programmer G. Xie
      * Version 1.0 date 22-03-1995 (Borland C++ V4.5)
      *
      * copyright (c) 1995 Dept. of Psychiatry, MCV, VCU

  ***************************************************************************

      * head file declares class TAsyncSocket

  ***************************************************************************

      */
     #ifndef TASYNCSOCKET.H
     #define TASYNCSOCKET.H

     #include <fstream.h>
     #include <owl\window.h>
     #include "winsock.h"
     #include "global.h" //define uint, DLLCLASS etc...

     //message id's
     enum
     {
      SM_HOSTNAME = WM_USER + 2100,
      SM_DATAREADY,
     };

     class Telnet;

     class DLLCLASS TAsyncSocket : public TWindow
     {
     public:
     int SelectRequest;
     TAsyncSocket(TWindow* pParent);

     ~TAsyncSocket();

     int Connect(const char* pHost, const char *pUser,
     const char *pPassword);
     bool ReConnect(const char* pHost, const char *pUser,
     const char *pPassword);
     int SyncRead(unsigned char *pData, int nMaxLen);
     int SyncSend(const unsigned char *pData, int nLen);
     int LastError();
     int Startup();

     void SetTelClient(Telnet *cl) { TelClient = cl; }
     void WantAll();
     void WantRead();
     void WantWrite();
      void WantNone();

     char Server[64]; // used to store server name
     char User[16]; // "" user name
     char Password[16]; // "" password

     SOCKET sock; // socket identifier
     bool bBlocking; // true if socket is blocking
     bool bConnected; // true if socket are connected
     bool bValid; // true if winsock.dll is valid

     protected:
     int Connect(char* pHost, int nPort = 0, int nProtocol = PF_INET);
     int GenSocket(char* pHost, int nPort = 0, int nProtocol = PF_INET);
     int AsyncGetHostByName(const char* ServerName);

     void EvTimer(uint uTimerId);
     void CleanupWindow();
     void SetupWindow();

     LRESULT SmHostName(WPARAM,LPARAM);
     LRESULT SmDataReady(WPARAM,LPARAM);

     Telnet *TelClient; // high level object owns the socket
     hostent *pHostent; // ptr to host entry
     protoent *pProtoent; // ptr to proto entry

     HANDLE hAsync; // handle used for async Winsocket calls
     HINSTANCE hSockInstance;// HINSTANCE for socket
     WSADATA wsaData; // Winsocket data

     struct hostent Host; // instance of hostent
     struct protoent Proto; // instance of protoent
     struct sockaddr_in inetAddr;// instance of sockeaddr_in strucutre

     char *tmpBuffer;
     ofstream *ostra;
     ofstream *ostrb;

     DECLARE_RESPONSE_TABLE(TAsyncSocket);
     };

     #endif

     .cpp file


  /**************************************************************************
      * Programmer G. Xie
      * Version 1.0 date 22-03-1995 (Borland C++ V4.5)
      *
      * copyright (c) 1995 Dept. of Psychiatry, MCV, VCU

  ***************************************************************************

      * head file declares class TAsyncSocket

  ***************************************************************************

      */
     #include <string.h>
     #include <owl\window.h>

     #pragma hdrstop

     #include "socket.h"
     #include "telnet.h"
     #include "mxapp.h"

     const unsigned int VERSION_NEED = 0x101; // winsock version we need
     const int TIMEOUT_MS = 1000; // 1000 millisecs --1 sec--
     const int BLOCK_TIMEOUT = 10; // in seconds
     const int TIMER_ID = 1; // internal timer id
     const int TMPBUFFSZ = 128; // tmp working buffer size

     //TAsyncSocket event handlers
     DEFINE_RESPONSE_TABLE1(TAsyncSocket,TWindow)
     EV_WM_TIMER,
     EV_MESSAGE(SM_HOSTNAME, SmHostName),
     EV_MESSAGE(SM_DATAREADY, SmDataReady),
     END_RESPONSE_TABLE;

     TAsyncSocket::TAsyncSocket(TWindow* pParent) : TWindow(pParent)
     {
     Attr.Style &= ~WS_VISIBLE; // force window to be hidden
     bValid = false; // invalid until SetupWindow is hit
     bConnected = false; // invalid until connection is made
     hSockInstance = 0; // winsock library instance handle
     SelectRequest = 0;

     tmpBuffer = 0;
     TelClient = 0;

     //debug log file stream pointers
     ostra = new ofstream("sockdebg.inp");
     ostrb = new ofstream("sockdebg.out");
     }

     TAsyncSocket::~TAsyncSocket()
     {
      if(tmpBuffer) delete [] tmpBuffer;
      delete ostra;
      delete ostrb;

     if(hSockInstance)
     ::FreeLibrary(hSockInstance);

     if(!bValid) return;

     //TelClient->Cleanup();

     if(WSAIsBlocking()) //if we are blocking
     WSACancelBlockingCall(); //cancel the blocking call

     if(bConnected) //if we are connected
     closesocket(sock); //close the socket

     WSACleanup(); //clean up the Winsockets
     KillTimer(TIMER_ID); //and kill our timer
     }

     bool TAsyncSocket::ReConnect(const char* pHost, const char *pUser,
     const char *pPass)
     {
     if(!bValid) return false;

     if(!bConnected) //if it is not a reconnect
     {
     Connect(pHost, pUser, pPass);
     return bConnected;
     }

     int len = strlen(pHost);
     if(len < 64)
     strcpy(Server, pHost);
     else
     {
     strncpy(Server, pHost, 63);
     Server[63] = '\0';
     }

     len = strlen(pUser);
     if(len < 16)
     strcpy(User, pUser);
     else
     {
     strncpy(User, pUser, 15);
     User[15] = '\0';
     }

     len = strlen(pPass);
     if(len < 16)
     strcpy(Password, pPass);
     else
     {
     strncpy(Password, pPass, 15);
     Password[15] = '\0';
     }

     if(WSAIsBlocking()) //if we are blocking
     WSACancelBlockingCall(); //cancel the blocking call

     bConnected = false;

     int rv = GenSocket(Server);
     if(rv == 0)
     {
     //connect the socket, sock has been create before the call
     if(connect(sock, (sockaddr far *) &inetAddr, sizeof(sockaddr)) == 0)
     bConnected = true; //set connected flag if operation was ok

     if(bConnected) WantAll(); //let server starts negociation
     //first message should be FD_WRITE
     }
     return bConnected;
     }

     void TAsyncSocket::SetupWindow()
     {
     TWindow::SetupWindow();
     }

     //Cancels any blocking calls, closes the socket if we are
     //connected and kills the timer if necessary

     void TAsyncSocket::CleanupWindow()
     {
     TWindow::CleanupWindow(); //call parent cleanupwindow
     }

     //TAsyncSocket::Startup
     //Startup the sockets and check version #
     //Start our timer

     int TAsyncSocket::Startup()
     {

     int retval = WSAStartup(VERSION_NEED, &wsaData);

     switch(retval)
     {
     case 0:
     bValid = true;
     break;

     case WSASYSNOTREADY:
     Global::Message("system not ready, network function disabled",
     "WSAStartup error");
     break;

     case WSAVERNOTSUPPORTED:
     case WSAEINVAL:
     Global::Message("Winsock version incompatible",
     "Network Function Disabled");
     break;
     }
     //if we have a good version
     if(bValid) SetTimer(TIMER_ID, TIMEOUT_MS);
     return retval;
     }

     int TAsyncSocket::GenSocket(char* pHost, int nPort , int nProtocol)
     {
     if(!bValid) return 0;

     memset(&inetAddr, 0, sizeof(inetAddr)); //cleanup structure
     inetAddr.sin_family = nProtocol; //set protocol (always PF_INET)
     inetAddr.sin_port = htons(nPort); //0 let system bind a port
     inetAddr.sin_addr.s_addr = htonl(INADDR_ANY);

     if(bConnected) closesocket(sock);

     sock = socket(nProtocol, SOCK_STREAM, IPPROTO_TCP);

     if(sock == INVALID_SOCKET) //socket was not created ok
      return LastError(); //return WSAError
     else if(bind(sock, (LPSOCKADDR)&inetAddr, sizeof(inetAddr)) == SOCKET_ERROR)
      return LastError();
     return 0;
     }

     // TAsyncSocket::Connect() public function
     // Starts the process of an asynchronous connection
     // sets up portions of the internet address structure inetAddr
     // for use later when the host look up finishes, etc.
     // pHost -- ptr to desired host name
     // nPort -- local port number to use
     // nProtocol -- protocol, defaults PF_INET
     // Returns:
     // integer -- 0 on success, any other value is either a WinSocket error or
     // one of our defined errors

     int TAsyncSocket::Connect(char* pHost, int nPort, int nProtocol)
     {
     if(!bValid) return 0;

     int rv = GenSocket(pHost, nPort, nProtocol);

     if(rv == 0)
     return AsyncGetHostByName(pHost); //acquire the host asynchronously
     return rv; //return last error
     }

     int TAsyncSocket::Connect(const char* pHost, const char *pUser,
     const char *pPass)
     {
     int len = strlen(pHost);
     if(len < 64)
     strcpy(Server, pHost);
     else
     {
     strncpy(Server, pHost, 63);
     Server[63] = '\0';
     }

     len = strlen(pUser);
     if(len < 16)
     strcpy(User, pUser);
     else
     {
     strncpy(User, pUser, 15);
     User[15] = '\0';
     }

     len = strlen(pPass);
     if(len < 16)
     strcpy(Password, pPass);
     else
     {
     strncpy(Password, pPass, 15);
     Password[15] = '\0';
     }

     if(!bConnected) Connect(Server);
     return 0;
     }

     void TAsyncSocket::WantAll()
     {
     if(WSAAsyncSelect(sock, HWindow, SM_DATAREADY,
     FD_CONNECT | FD_WRITE | FD_READ | FD_CLOSE) == SOCKET_ERROR)
     Global::Message("in Select network events", "WSASelect error");
     }

     void TAsyncSocket::WantRead()
     {
     if(WSAAsyncSelect(sock, HWindow, SM_DATAREADY, FD_READ) ==
     SOCKET_ERROR)
     Global::Message("in Select network read", "WSASelect error");
     }

     void TAsyncSocket::WantWrite()
     {
     if(WSAAsyncSelect(sock, HWindow, SM_DATAREADY, FD_WRITE) ==
     SOCKET_ERROR)
     Global::Message("in Select network write", "WSASelect error");
     }

     //TAsyncSocket::AsyncGetHostByName
     //Starts an asyncronous host name lookup
     //stores the returned handle in hAsync
     //pHost : ptr to host name
     //Returns: 0 if ok, LastError() if a problem was encountered

     int TAsyncSocket::AsyncGetHostByName(const char* pHost)
     {
     //send HWindow a SM_HOSTNAME message, with hostent
     //structure copied in ReadBuffer

     unsigned long IPAddress;

     if(tmpBuffer == 0) tmpBuffer = new char [TMPBUFFSZ + 1];

     if(pHost[0] >= '0' && pHost[0] <= '9')
      {
      IPAddress = inet_addr(pHost);
     hAsync = WSAAsyncGetHostByAddr(HWindow, SM_HOSTNAME, (char *)
  &IPAddress,
     4, PF_INET, tmpBuffer, TMPBUFFSZ);
      }
     else
     hAsync = WSAAsyncGetHostByName(HWindow, SM_HOSTNAME, pHost,
     tmpBuffer, TMPBUFFSZ);

     //use synchorous call to get host, asynchorous call sometimes not working
     //pHostent = gethostbyname("electro");
     /*
      char lpzmessage[100];
      char lpzIP[16];

      //setup host structures,, copy hostent structure back
      memcpy(&inetAddr.sin_addr, pHostent->h_addr, pHostent->h_length);

      inetAddr.sin_family = PF_INET;
      inetAddr.sin_port = htons(IPPORT_TELNET);

      wsprintf(lpzmessage, "Host %s has IP address ", pHostent->h_name);
      wsprintf(lpzIP, "%s", inet_ntoa(inetAddr.sin_addr));
      lstrcat(lpzmessage, lpzIP);
      mxApp::GPMxApp->SetMessageText(lpzmessage);

      //connect the socket, sock has been create before the call
      if(connect(sock, (sockaddr far *) &inetAddr, sizeof(sockaddr)) == 0)
     bConnected = true; //set connected flag if operation was ok
      if(bConnected) WantAll(); //let server starts negociation

     return 0;
     */

     if (hAsync == 0) //if we did not receive a handle
     return LastError(); //return socket error
     else //otherwise
     return 0; //return 0 for success
     }

     //TAsyncSocket::SmHostName
     //receives host name notification and connects the socket
     //WSAGETSELECTERROR(lp) error information
     //WSAGETSELECTEVENT(lp) event code

     LRESULT TAsyncSocket::SmHostName(WPARAM /* wp */, LPARAM lp)
     {
      char lpzmessage[100];
      char lpzIP[16];

      WSACancelAsyncRequest(hAsync); //cancel async requests
      if(WSAGETSELECTERROR(lp) == 0)
     {
     //setup host structures,, copy hostent structure back
     memcpy(&Host, tmpBuffer, sizeof(Host));
     memcpy(&inetAddr.sin_addr, Host.h_addr, Host.h_length);

     inetAddr.sin_family = PF_INET;
     inetAddr.sin_port = htons(IPPORT_TELNET);

     sprintf(lpzmessage, "Contact Host %s with IP address ", Host.h_name);
     sprintf(lpzIP, "%s", inet_ntoa(inetAddr.sin_addr));
     strcat(lpzmessage, lpzIP);
     mxApp::GPMxApp->SetMessageText(lpzmessage);
     mxApp::GPMxApp->PumpWaitingMessages();

     //connect the socket, sock has been create before the call
     if(connect(sock, (sockaddr far *) &inetAddr, sizeof(sockaddr)) == 0)
     bConnected = true; //set connected flag if operation was ok

     if(bConnected) WantAll(); //let server starts negociation
      }
      delete [] tmpBuffer; tmpBuffer = 0;
      return true;
     }

     //Returns the last WinSocket error encountered
     //if the error is not connect, try to do reconnect

     int TAsyncSocket::LastError()
     {
      if(!bValid) return 0;

     int rv = WSAGetLastError();
     if(rv == WSAENOTCONN && bConnected)
     {
     if(WSAIsBlocking()) //if we are blocking
     WSACancelBlockingCall(); //cancel the blocking call

     bConnected = false;

     int rn = GenSocket(Server);
     if(rn == 0)
     {
     if(connect(sock, (sockaddr far *) &inetAddr, sizeof(sockaddr)) == 0)
     bConnected = true; //set connected flag if operation was ok
     if(bConnected) WantAll(); //let server starts negociation
     //first message should be FD_WRITE
     }
     }
     return rv;
     }

     //TAsyncSocket::SyncSend
     //Syncronous send, use for small amounts of data
     //pData -- ptr to data to send
     //nLen -- length of data
     //Returns:
     // integer -- SOCKET_ERROR - extract error info with LastError()
     // -- Anything else - contains amount of data sent

     int TAsyncSocket::SyncSend(const unsigned char * pData, int nLen)
     {
      if(!bValid) return 0;

     if(WSAIsBlocking()) return 0;

     int rv = send(sock, (char *) pData, nLen, 0);
     if(rv == SOCKET_ERROR)
     {
     int lasterror = LastError();
     if(lasterror == WSAEWOULDBLOCK)
     { return 0; }
     Global::Message((char *) pData, "Socket Send Error");
     return 0;
     }
     *ostrb << pData << endl;
     return rv;
     }

     //TAsyncSocket::SyncRead
     //Syncronous recv, use when you expect small amounts of data
     //pData -- ptr to data for storage
     //nMaxLen -- max length of data
     //Returns:
     // integer -- SOCKET_ERROR - extract error info with LastError()
     // -- Anything else - contains amount of data received

     int TAsyncSocket::SyncRead(unsigned char * pData, int nMaxLen)
     {
      if(!bValid) return 0;

     if(WSAIsBlocking()) return 0;

     memset(pData, 0, nMaxLen-1);

     int rv = recv(sock, (char *) pData, nMaxLen, 0);
     *ostra << pData << endl;

     if(rv == SOCKET_ERROR)
     {
     int lasterror = LastError();
     if(lasterror == WSAEWOULDBLOCK)
     { return 0; }
     Global::Message((char *) pData, "Socket Read Error");
     return 0;
     }
     return rv;
     }

     //TAsyncSocket::EvTimer
     //Catches potential blocking problems and times out
     //after BLOCK_TIMEOUT number of seconds

     static int bTick = 0;
     static bool bInTimer = false;

     void TAsyncSocket::EvTimer(uint /* uTimerId */)
     {
      if(!bValid) return;

     if (!bInTimer)
     {
     bInTimer = true;
     if (WSAIsBlocking())
     {
     bTick++;
     if (bTick > BLOCK_TIMEOUT)
     {
     WSACancelBlockingCall();
     Global::Message("cancel blocking call","Error in EvTimer");
     }
     }
     else bTick = 0;
     bInTimer = false;
     }
     }

     void TAsyncSocket::WantNone()
     {
     //cancel any previous selection
     WSAAsyncSelect(sock, HWindow, 0, 0);
     }

     LRESULT TAsyncSocket::SmDataReady(WPARAM wp, LPARAM lp)
     {
     if(WSAGETSELECTERROR(lp) != 0) return true;

     WSAAsyncSelect(sock, HWindow, 0, 0);

     if(WSAGETSELECTEVENT(lp) == FD_CLOSE)
      {
      if(TelClient)
      {
     if(TelClient->Read())
     {
     PostMessage(SM_DATAREADY, wp, lp);
     return true;
     }
     }
      bConnected = false; closesocket(sock); return true;
      }

     else if(WSAGETSELECTEVENT(lp) == FD_CONNECT)
      {
      }

     else if(WSAGETSELECTEVENT(lp) == FD_READ)
      {
      if(TelClient) TelClient->Read();
      }

     else if(WSAGETSELECTEVENT(lp) == FD_WRITE)
      {
      if(TelClient) TelClient->Send();
      }

     return true;
     }
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
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.

743 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now