🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.internet.socket
Article #2708

Re: Too many calls to OnRead

#2708
From: marko.suonpera
Date: Tue, 14 Feb 2006 09:37
348 lines
10528 bytes
Ok, I made a new version. Here I create a buffer between the sockets
and read and write by the application. In the sending machine I use the
buffer "send" to hold data. Vector is written into the buffer,
preceeded by its size. "writepos" shows the place where next byte
should be written. "readpos" shows the place where the next byte should
be read when writing to the socket.

In the receiving machine data is read into buffer "rec" whenever
Onread() is called. writepos shows the place where next character
should be written. It is always increased by the amount that
receivebuf() returns. The readpos is not used for this buffer,
readvector() always tries to read the whole vector out of the receive
buffer to the user application. If this succeeds, it shifts the buffer
by the function Rollback() so that the next vector should again start
from the beginning of the buffer.

However, I am a bit confused about receivebuf(). Suppose there is for
example 200 bytes in the socket internal buffer and receivelength()
returns 200. Now should I just try to read 200 bytes? If I just read 10
bytes, which bytes do I get the next time? Is OnRead() called as long
as there is something to read? What is the difference between trying to
read the amount returned by receivelength() and a very big number of
bytes?

And now the code:



#include <ScktComp.hpp>
#include <vector>

using std::vector;

class Buffer
{
public:
    char data[5000];
    const int bufsize;
    int writepos, readpos;
    Buffer(): bufsize(5000) { writepos = 0; readpos = 0;}

    void RollBack(int);
};

class Tcpmessager
{
private:
    TClientSocket *ClientSocket;
    TServerSocket *ServerSocket;

    vector<double> v;
    Buffer rec, send;

    bool WriteVectorToBuf(const vector<double> &u);
public:
    Tcpmessager(TComponent* owner);
    ~Tcpmessager(void);

    AnsiString currenthost;

    void FileListen(void);
    void FileConnect(AnsiString _host);
    void FileDisconnect(void);
    bool SendFromBuf(TCustomWinSocket *Socket);
    bool ReadInBuf(TCustomWinSocket *Socket);
    bool ReadVector(void);
    bool WriteVector(const vector<double> &u);

    void GetVector(vector<double> &u) {u = v;}

    //void __fastcall ServerSocketError(TObject* Sender, short Number,
AnsiString &Description, int Scode
	//	, const AnsiString Source, const AnsiString HelpFile, int
HelpContext, Word &CancelDisplay);
    void __fastcall ServerSocketError(TObject* Sender,
TCustomWinSocket* Socket,
    TErrorEvent ErrorEvent, int &ErrorCode);
    void  __fastcall ClientSocketConnect(TObject* Sender,
TCustomWinSocket* Socket);
    void  __fastcall ClientSocketRead(TObject* Sender,
TCustomWinSocket* Socket);
    void  __fastcall ServerSocketClientRead(TObject* Sender,
TCustomWinSocket* Socket);
    void __fastcall ClientSocketWrite(TObject* Sender,
TCustomWinSocket* Socket);
    void __fastcall ServerSocketClientWrite(TObject* Sender,
TCustomWinSocket* Socket);

    void  __fastcall ServerSocketAccept(TObject* Sender,
TCustomWinSocket* Socket);
    void  __fastcall ServerSocketClientConnect(TObject* Sender,
TCustomWinSocket* Socket);
    void  __fastcall ClientSocketDisconnect(TObject* Sender,
TCustomWinSocket* Socket);
    void  __fastcall ClientSocketError(TObject* Sender,
TCustomWinSocket* Socket, TErrorEvent ErrorEvent
	, int &ErrorCode);
    void  __fastcall ServerSocketClientDisconnect(TObject* Sender,
TCustomWinSocket* Socket);
};

CPP:



Tcpmessager::Tcpmessager(TComponent* owner)
{
    ClientSocket = new TClientSocket(owner);
    ServerSocket = new TServerSocket(owner);

    ServerSocket->OnAccept = &ServerSocketAccept;
    ServerSocket->OnClientConnect = &ServerSocketClientConnect;
    ServerSocket->OnClientDisconnect = &ServerSocketClientDisconnect;
    ServerSocket->OnClientRead = &ServerSocketClientRead;
    ServerSocket->OnClientError = &ServerSocketError;
    ServerSocket->OnClientWrite = &ServerSocketClientWrite;

    ClientSocket->OnConnect = &ClientSocketConnect;
    ClientSocket->OnDisconnect = &ClientSocketDisconnect;
    ClientSocket->OnError = &ClientSocketError;
    ClientSocket->OnRead = &ClientSocketRead;
    ClientSocket->OnWrite = &ClientSocketWrite;

    ServerSocket->ServerType = stNonBlocking;
    ServerSocket->Port = 1024;
    ClientSocket->ClientType = ctNonBlocking;
    ClientSocket->Port = 1024;

    currenthost = "";
}

Tcpmessager::~Tcpmessager(void)
{
    ServerSocket->Close();
	ClientSocket->Close();
    delete ServerSocket;
    delete ClientSocket;

}

void Tcpmessager::FileListen(void)
{
    ClientSocket->Close();
    ServerSocket->Open();
}

void Tcpmessager::FileConnect(AnsiString _host)
{
    if (ClientSocket->Active) ClientSocket->Active = false;

    if (_host.Length() > 0){
			ClientSocket->Host = _host;
			ClientSocket->Open();
    }

}

void Tcpmessager::FileDisconnect(void)
{
    ClientSocket->Close();
    ServerSocket->Close();
}

bool  Tcpmessager::SendFromBuf(TCustomWinSocket *Socket)
{
    LPBYTE pBuf = (LPBYTE) send.data;
    int sendamount = send.writepos - send.readpos;
    if (sendamount == 0) return true;

    int sent = Socket->SendBuf(pBuf+send.readpos, sendamount);
    if( sent < 0 )
    {
        if( WSAGetLastError() != WSAEWOULDBLOCK ) return false;
        sent = 0;   //WSAEWOULDBLOCK
    }
    else if( sent == 0 ) // socket disconnected
    {
        return false;
    }

    send.readpos += sent;

    if (send.readpos > send.bufsize * 0.5) send.RollBack(send.readpos);
    return true;
}

bool Tcpmessager::ReadInBuf(TCustomWinSocket *Socket)
{
    LPBYTE pBuf = (LPBYTE) (rec.data + rec.writepos);

    int k = Socket->ReceiveLength();

    int read = Socket->ReceiveBuf(pBuf , k);
    if( read < 0 )
    {
        if( WSAGetLastError() != WSAEWOULDBLOCK ) return false;  //real
error
        read = 0;   //WSAEWOULDBLOCK
    }
    else if( read == 0 )// socket disconnected
    {
        return false;
    }

    rec.writepos += read;

    return true;
}

bool Tcpmessager::ReadVector(void)
{
    int s = 0;
    if (rec.writepos > sizeof(int))
    {
        s = *((int*)rec.data);
        if (s < 0 || s > 500000) return false;
        v.resize(s);
    }
    else return false;

    if (rec.writepos < s * sizeof(double) + sizeof(int)) return false;

    double *a = (double*)(rec.data + sizeof(int));

    for(int i=0;i < s;i++)
        v[i] = *(a+i);

    //roll read buffer by the suitable amount of bytes
    rec.RollBack(s * sizeof(double) + sizeof(int));
    return true;
}

bool Tcpmessager::WriteVectorToBuf(const vector<double> &u)
{
    int n = u.size();
    if (send.bufsize - send.writepos < n*sizeof(double) + sizeof(int))
return false;

    *((int*)(send.data + send.writepos)) = n;
    send.writepos += sizeof(int);

    for(int i = 0; i < n; i++)
    {
        *((double*)(send.data + send.writepos)) = u[i];
        send.writepos += sizeof(double);
    }
    return true;
}

bool Tcpmessager::WriteVector(const vector<double> &u)
{
    TCustomWinSocket *Socket;

    if (ClientSocket->Active) Socket = ClientSocket->Socket;
    else if (ServerSocket->Socket->ActiveConnections > 0)
        Socket = ServerSocket->Socket->Connections[0];
    else return false;

    if (!WriteVectorToBuf(u)) return false;

    //now call sendfrombuf() to send the data
    return (SendFromBuf(Socket));
}



void __fastcall Tcpmessager::ClientSocketConnect(TObject* Sender,
TCustomWinSocket* Socket)
{
    currenthost = Socket->RemoteHost;
}

void __fastcall Tcpmessager::ClientSocketRead(TObject* Sender,
TCustomWinSocket* Socket)
{
    ReadInBuf(Socket);

}

void __fastcall Tcpmessager::ServerSocketClientRead(TObject* Sender,
TCustomWinSocket* Socket)
{
    ReadInBuf(Socket);
}

void __fastcall Tcpmessager::ClientSocketWrite(TObject* Sender,
TCustomWinSocket* Socket)
{
    SendFromBuf(Socket);
}

void __fastcall Tcpmessager::ServerSocketClientWrite(TObject* Sender,
TCustomWinSocket* Socket)
{
    SendFromBuf(Socket);
}

void __fastcall Tcpmessager::ServerSocketAccept(TObject*
 Sender, TCustomWinSocket* Socket)
{
    //nothing
}

void __fastcall Tcpmessager::ServerSocketClientConnect(TObject* Sender,
TCustomWinSocket* Socket)
{
    currenthost = Socket->RemoteHost;
}

void __fastcall Tcpmessager::ServerSocketClientDisconnect(TObject*
Sender, TCustomWinSocket* Socket)
{
    ServerSocket->Close();
	ServerSocket->Open();
    currenthost = "";
}

void __fastcall Tcpmessager::ClientSocketDisconnect(TObject* Sender,
TCustomWinSocket* Socket)
{
    currenthost = "";
}

void  __fastcall Tcpmessager::ClientSocketError(TObject* Sender,
TCustomWinSocket* Socket, TErrorEvent ErrorEvent
	, int &ErrorCode)
{
    //show error msg
    ErrorCode = 0;
}

void __fastcall Tcpmessager::ServerSocketError(TObject* Sender,
TCustomWinSocket* Socket,
    TErrorEvent ErrorEvent, int &ErrorCode)
{
     //show error msg
    ErrorCode = 0;
}

void Buffer::RollBack(const int a)
{
    if (a > 0 && a < bufsize)
    {
        memcpy(data, data + a, bufsize - a);
        readpos -= a;
        writepos -= a;
    }
}
Technical Details
Message-ID: <1139909861.367820.22470@g44g2000cwa.googlegroups.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!postnews.google.com!g44g2000cwa.googlegroups.com!not-for-mail
References: <1139739145.875731.77940@g44g2000cwa.googlegroups.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,45664700a055b46a
X-Google-Attributes: gid11508e,public
X-Google-Language: ENGLISH,ASCII-7-bit
Path: arc1-ca.pugleaf.net!g2news1.google.com!postnews.google.com!g44g2000cwa.googlegroups.com!not-for-mail
From: marko.suonpera@24net.zzn.com
Newsgroups: borland.public.cppbuilder.internet.socket
Subject: Re: Too many calls to OnRead
Date: 14 Feb 2006 01:37:41 -0800
Organization: http://groups.google.com
Lines: 349
Message-ID: <1139909861.367820.22470@g44g2000cwa.googlegroups.com>
References: <1139739145.875731.77940@g44g2000cwa.googlegroups.com>
NNTP-Posting-Host: 130.188.8.11
Mime-Version: 1.0
Content-Type: text/plain; charset="iso-8859-1"
X-Trace: posting.google.com 1139909866 25998 127.0.0.1 (14 Feb 2006 09:37:46 GMT)
X-Complaints-To: groups-abuse@google.com
NNTP-Posting-Date: Tue, 14 Feb 2006 09:37:46 +0000 (UTC)
In-Reply-To: <1139739145.875731.77940@g44g2000cwa.googlegroups.com>
User-Agent: G2/0.2
X-HTTP-UserAgent: Opera/7.54u1 (Windows NT 5.1; U)  [en],gzip(gfe),gzip(gfe)
Complaints-To: groups-abuse@google.com
Injection-Info: g44g2000cwa.googlegroups.com; posting-host=130.188.8.11;
   posting-account=UpYnTw0AAADMPWcPv43CBbekFgE2xLoE