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.
User contributions licensed under CC BY-SA 3.0