🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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

Too many calls to OnRead

#2702
From: marko.suonpera
Date: Sun, 12 Feb 2006 10:12
310 lines
9192 bytes
So what's wrong with this code? I create the class Tcpmessager to
handle sending and receiving standard library vectors from another
machine. Either machine could be either server or client.

So when I give std::vector<double> with 15 elements as input to
WriteVector, everything works fine if I have the debugger on in the
receiving machine. If it is not on, I am more likely to get crap.
However, when ReadVector() has finished, OnRead() or OnClientRead()
immediately fire again. If the receiving machine is the server, nothing
gets read here. Then in Application->ProcessMessages() OnRead is called
again and I get a lot of nested calls to ReadVector (7-8 calls
alltogether).  If the receiving machine is the server, nothing gets
read, so it is no problem. But if it is the client, sometimes a very
big number, or zero,  is read as the vector size (s) on the additional
calls to OnRead and this produces errors.

Then again WriteVector always succeeds (returns true).

So I use the nonblocking mode. When I turned to blocking, the OnRead
events are never called.

I'd like the program to be able to handle vectors of at least 100000
elements long.

//---------------------------------------------------------------------------
#ifndef tcpmessagerH
#define tcpmessagerH
//---------------------------------------------------------------------------

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

using std::vector;

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

    vector<double> v;

public:
    Tcpmessager(TComponent* owner);
    ~Tcpmessager(void);

    bool vectorwasread;
    AnsiString currenthost;

    void FileListen(void);
    void FileConnect(AnsiString _host);
    void FileDisconnect(void);
    bool SendData(TCustomWinSocket *Socket, void *Buffer, int BufSize);
    bool ReadData(TCustomWinSocket *Socket, void *Buffer, int BufSize);
    bool ReadVector(TCustomWinSocket *Socket);
    bool WriteVector(const vector<double> &u);

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

    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 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);
};

#endif



tcpmessager.cpp:

#include "tcpmessager.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)


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;

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

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

    vectorwasread = false;
    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::SendData(TCustomWinSocket *Socket, void *Buffer, int
BufSize)
{
    LPBYTE pBuf = (LPBYTE) Buffer;

    while( BufSize > 0 )
    {
        int sent = Socket->SendBuf(pBuf, BufSize);
        if( sent < 0 )
        {
            if( WSAGetLastError() != WSAEWOULDBLOCK ) return false;

            Application->ProcessMessages();
            continue;
        }

        if( sent == 0 ) // socket disconnected
        {
            return false;
        }

        pBuf += sent;
        BufSize -= sent;
    }
    return true;
}

bool Tcpmessager::ReadData(TCustomWinSocket *Socket, void *Buffer, int
BufSize)
{
    LPBYTE pBuf = (LPBYTE) Buffer;

    while( BufSize > 0 )
    {
        int read = Socket->ReceiveBuf(pBuf, BufSize);
        if( read < 0 )
        {
            if( WSAGetLastError() != WSAEWOULDBLOCK ) return false;

            Application->ProcessMessages();
            continue;
        }

        if( read == 0 ){
                // socket disconnected
            return false;
        }

        pBuf += read;
        BufSize -= read;
    }
    return true;
}

bool Tcpmessager::ReadVector(TCustomWinSocket *Socket)
{
    int s = 0;

    if( ReadData(Socket, &s, sizeof(int)) && s > 0)
    {
        v.resize(s);
        for(int i = 0; i < s; i++)
        {
            if(!ReadData(Socket, &(v[i]), sizeof(double)) )
                return false;
        }
    }
    else return false;

    return true;
}

bool Tcpmessager::WriteVector(const vector<double> &u)
{
    TCustomWinSocket *Socket;
    int n = u.size();
    double temp;

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

    if( SendData(Socket, &(n), sizeof(int)) )
    {
        for(int i = 0; i < n; i++)
        {
            temp = u[i];
            if( !SendData(Socket, &temp, sizeof(double)) )
                return false;
        }
    }
    else return false;

    return true;
}



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

void __fastcall Tcpmessager::ClientSocketRead(TObject* Sender,
TCustomWinSocket* Socket)
{
    ReadVector(Socket);
    vectorwasread = true;
}

void __fastcall Tcpmessager::ServerSocketClientRead(TObject* Sender,
TCustomWinSocket* Socket)
{
    ReadVector(Socket);
    vectorwasread = true;
}

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;
}
Technical Details
Message-ID: <1139739145.875731.77940@g44g2000cwa.googlegroups.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!postnews.google.com!g44g2000cwa.googlegroups.com!not-for-mail

Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,45664700a055b46a,start
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: Too many calls to OnRead
Date: 12 Feb 2006 02:12:25 -0800
Organization: http://groups.google.com
Lines: 311
Message-ID: <1139739145.875731.77940@g44g2000cwa.googlegroups.com>
NNTP-Posting-Host: 130.188.8.10
Mime-Version: 1.0
Content-Type: text/plain; charset="iso-8859-1"
X-Trace: posting.google.com 1139739150 12545 127.0.0.1 (12 Feb 2006 10:12:30 GMT)
X-Complaints-To: groups-abuse@google.com
NNTP-Posting-Date: Sun, 12 Feb 2006 10:12:30 +0000 (UTC)
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.10;
   posting-account=UpYnTw0AAADMPWcPv43CBbekFgE2xLoE