Article View: borland.public.cppbuilder.internet.socket
Article #2708Re: Too many calls to OnRead
From: marko.suonpera
Date: Tue, 14 Feb 2006 09:37
Date: Tue, 14 Feb 2006 09:37
348 lines
10528 bytes
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-mailReferences:
<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