Socket Library defect Not receiving responses MQL C#

-3

Here is the library that I am trying to work out with:

#property strict


// -------------------------------------------------------------
// WinInet constants and structures
// -------------------------------------------------------------

#define SOCKET_HANDLE32       uint
#define SOCKET_HANDLE64       ulong
#define AF_INET               2
#define SOCK_STREAM           1
#define IPPROTO_TCP           6
#define INVALID_SOCKET32      0xFFFFFFFF
#define INVALID_SOCKET64      0xFFFFFFFFFFFFFFFF
#define SOCKET_ERROR          -1
#define INADDR_NONE           0xFFFFFFFF
#define FIONBIO               0x8004667E
#define WSAWOULDBLOCK         10035

struct sockaddr {
   short family;
   ushort port;
   uint address;
   ulong ignore;
};

// -------------------------------------------------------------
// DLL imports
// -------------------------------------------------------------

#import "ws2_32.dll"
   // Imports for 32-bit environment
   SOCKET_HANDLE32 socket(int, int, int);
   int connect(SOCKET_HANDLE32, sockaddr&, int);
   int closesocket(SOCKET_HANDLE32);
   int send(SOCKET_HANDLE32, uchar&[],int,int);
   int recv(SOCKET_HANDLE32, uchar&[], int, int);
   int ioctlsocket(SOCKET_HANDLE32, uint, uint&);
   int bind(SOCKET_HANDLE32, sockaddr&, int);
   int listen(SOCKET_HANDLE32, int);
   SOCKET_HANDLE32 accept(SOCKET_HANDLE32, int, int);

   // Imports for 64-bit environment
   SOCKET_HANDLE64 socket(int, int, uint);
   int connect(SOCKET_HANDLE64, sockaddr&, int);
   int closesocket(SOCKET_HANDLE64);
   int send(SOCKET_HANDLE64, uchar&[], int, int);
   int recv(SOCKET_HANDLE64, uchar&[], int, int);
   int ioctlsocket(SOCKET_HANDLE64, uint, uint&);
   int bind(SOCKET_HANDLE64, sockaddr&, int);
   int listen(SOCKET_HANDLE64, int);
   SOCKET_HANDLE64 accept(SOCKET_HANDLE64, int, int);

   // Neutral; no difference between 32-bit and 64-bit
   uint inet_addr(uchar&[]);
   uint gethostbyname(uchar&[]);
   ulong gethostbyname(char&[]);
   int WSAGetLastError();
   uint htonl(uint);
   ushort htons(ushort);
#import

// For navigating the hostent structure, with indescribably horrible variation
// between 32-bit and 64-bit
#import "kernel32.dll"
   void RtlMoveMemory(uint&, uint, int);
   void RtlMoveMemory(ushort&, uint, int);
   void RtlMoveMemory(ulong&, ulong, int);
   void RtlMoveMemory(ushort&, ulong, int);
#import


// -------------------------------------------------------------
// Client socket class
// -------------------------------------------------------------

class ClientSocket
{
   private:
      // Need different socket handles for 32-bit and 64-bit environments
      SOCKET_HANDLE32 mSocket32;
      SOCKET_HANDLE64 mSocket64;

      // Other state variables
      bool mConnected;
      int mLastWSAError;
      string mPendingReceiveData;

   public:
      ClientSocket(ushort localport);
      ClientSocket(string HostnameOrIPAddress, ushort localport);

      ClientSocket(SOCKET_HANDLE32 clientsocket32);
      ClientSocket(SOCKET_HANDLE64 clientsocket64);

      ~ClientSocket();
      bool Send(string strMsg);
      string Receive(string MessageSeparator = "");

      bool IsSocketConnected() {return mConnected;}
      int GetLastSocketError() {return mLastWSAError;}
};


ClientSocket::ClientSocket(SOCKET_HANDLE32 clientsocket32)
{
   // Need to create either a 32-bit or 64-bit socket handle
   mConnected = true;
   mSocket32 = clientsocket32;
}

ClientSocket::ClientSocket(SOCKET_HANDLE64 clientsocket64)
{
   // Need to create either a 32-bit or 64-bit socket handle
   mConnected = true;
   mSocket64 = clientsocket64;
}


// -------------------------------------------------------------
// Destructor. Close the socket if created
// -------------------------------------------------------------

ClientSocket::~ClientSocket()
{
   if (TerminalInfoInteger(TERMINAL_X64)) {
      if (mSocket64 != 0)  closesocket(mSocket64);
   } else {
      if (mSocket32 != 0)  closesocket(mSocket32);
   }   
}



string ClientSocket::Receive(string MessageSeparator = "")
{
   if (!mConnected) return "";
   //Sleep(200);
   string strRetval = "";

   uchar arrBuffer[];
   int BufferSize = 10000;
   ArrayResize(arrBuffer, BufferSize);

   uint nonblock = 1;
   ioctlsocket(mSocket64, FIONBIO, nonblock);

      int res = 1;
      while (res > 0) {
         res = recv(mSocket64, arrBuffer, BufferSize, 0);

         if (res > 0) {
            StringAdd(mPendingReceiveData, CharArrayToString(arrBuffer, 0, res));
            //ArrayPrint(arrBuffer);
         } else {
         //Print(res, "false");
            if (WSAGetLastError() != WSAWOULDBLOCK) mConnected = false;
         }
      }

   if (mPendingReceiveData == "") {
      // No data

   } else if (MessageSeparator == "") {
      // No requested message separator to wait for
      strRetval = mPendingReceiveData;
      mPendingReceiveData = "";;

   } else {
      int idx = StringFind(mPendingReceiveData, MessageSeparator);
      if (idx >= 0) {
         while (idx == 0) {
            mPendingReceiveData = StringSubstr(mPendingReceiveData, idx + StringLen(MessageSeparator));
            idx = StringFind(mPendingReceiveData, MessageSeparator);
         }

         strRetval = StringSubstr(mPendingReceiveData, 0, idx);
         mPendingReceiveData = StringSubstr(mPendingReceiveData, idx + StringLen(MessageSeparator));
      }
   }
   ArrayFree(arrBuffer);
   return strRetval;
}

Using the above library I am not able to receive the output from the server. Whenever I tried I got a blank response.

So I tried the following looping till the response is received:

string ClientSocket :: Receive ( string MessageSeparator = "" )
{
   if (! mConnected) return  "" ;
   // Sleep (200); 
   string strRetval = "" ;

   uchar arrBuffer [];
   int BufferSize = 10000 ;
   ArrayResize (arrBuffer, BufferSize);

   uint nonblock = 1 ;
   if ( TerminalInfoInteger ( TERMINAL_X64 )) {
      ioctlsocket (mSocket64, FIONBIO, nonblock);

       int res = 1 ;
       while (res> 0 ) {
         res = recv (mSocket64, arrBuffer, BufferSize, 0 );
         // Print (res); 
         while (res < 0 )
         {
         res = recv (mSocket64, arrBuffer, BufferSize, 0 );
         // Print (res);
         }

         // Print (res); 
         // Print (WSAGetLastError ()); 
         if (res> 0 ) {
              StringAdd (mPendingReceiveData, CharArrayToString (arrBuffer, 0 , res));
             // ArrayPrint (arrBuffer); 
         } else {
          // Print (res, "false"); 
             if (WSAGetLastError ()! = WSAWOULDBLOCK) mConnected = false ;
         }
      }
   } else {
      ioctlsocket (mSocket32, FIONBIO, nonblock);

       int res = 1 ;
       while (res> 0 ) {
         res = recv (mSocket32, arrBuffer, BufferSize, 0 );

         if (res> 0 ) {
              StringAdd (mPendingReceiveData, CharArrayToString (arrBuffer, 0 , res));
         } else {
              if (WSAGetLastError ()! = WSAWOULDBLOCK) mConnected = false ;
         }
      }
   }   

   if (mPendingReceiveData == "" ) {
        // No data

   } else  if (MessageSeparator == "" ) {
        // No request message
      strRetval = mPendingReceiveData;
      mPendingReceiveData = "" ;;

   } else {
        int idx = StringFind (mPendingReceiveData, MessageSeparator);
       if (idx> = 0 ) {
          while (idx == 0 ) {
            mPendingReceiveData = StringSubstr (mPendingReceiveData, idx + StringLen (MessageSeparator));
            idx = StringFind (mPendingReceiveData, MessageSeparator);
         }

         strRetval = StringSubstr (mPendingReceiveData, 0 , idx);
         mPendingReceiveData = StringSubstr (mPendingReceiveData, idx + StringLen (MessageSeparator));
      }
   }
   ArrayFree (arrBuffer);
   return strRetval;
}

This worked for a while. But when there was no response received from the server, it went into an infinite loop and has stopped my program.

Kindly, suggest me the best way what I can do improve the code and make my library robust.

sockets
winapi
mql5
metatrader5
asked on Stack Overflow Nov 9, 2018 by Jaffer Wilson • edited Nov 12, 2018 by Jaffer Wilson

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0