Article View: borland.public.cppbuilder.internet.socket
Article #5255Re: Client: ctNonBlocking -> Server: stThreadBlocking
From: Remy Lebeau (TeamB)
Date: Mon, 27 Sep 2004 19:54
Date: Mon, 27 Sep 2004 19:54
169 lines
6074 bytes
6074 bytes
"Vladimir Stefanovic" <spam@not.needed> wrote in message
news:415856d5@newsgroups.borland.com...
> How can I send data with TClientSocket
> in ctNonBlocking to Server.
The same way you send it with ctBlocking. The only thing you have to watch
out for is that ctNonBlocking may not always be able to accept new data
because it may block the socket. In that case, you have to check the return
value of SendBuf(). If it returns -1, you have to wait for the socket's
OnWrite event to be triggered before you can write data to the socket again.
> I have the sending code which only works when the mode
> is ctBlocking. What can I do to modify the code to work
> in ctNonBlocking mode?
The easily way is to simply call Application->ProcessMessages() inside your
loop whenever SendBuf() returns -1 so that OnWrite can be processed. This
would essentially make the code act like blocking code.. -1 is *NOT* an
error for a non-blocking socket unless the OnError event is triggered.
Otherwise, -1 simply means that the socket would have been blocked, but the
socket is otherwise still valid. For example (untested):
void __fastcall TcliForm::SendButtonClick(TObject *Sender)
{
if( (!ClientSocket->Active) || (!ClientSocket->Socket->Connected) )
return;
SendButtonClick->Enabled = false;
int NumberOfBytes = OutboxDataBuffer->Size;
bool bSent = SendData(&NumberOfBytes, sizeof(int));
if( bSent )
bSent = SendData(OutboxDataBuffer->Memory, NumberOfBytes);
if( !bSent )
ShowMessage( "Error!" );
SendButtonClick->Enabled = true;
}
bool __fastcall TcliForm::SendData(void* Buffer, int BufSize)
{
LPBYTE pBuffer = (LPBYTE) pBuffer;
int TotalSent = 0;
try
{
while( TotalSent < BufSize )
{
int NumberOfBytesSent =
ClientSocket->Socket->SendBuf(&pBuffer[TotalSent], BufSize-TotalSent);
if( NumberOfBytes == -1 )
Application->ProcessMessages();
else
TotalSent += NumberOfBytes;
}
return true;
}
catch(const Exception &)
{
return false;
}
}
Otherwise, you will have to re-write the code to use a queing system
instead, for example (untested):
#define APPWM_SEND_DATA (WM_APP+100)
__fastcall TcliForm::TcliForm(TComponent* Owner)
: TForm(Owner)
{
OutboxDataBuffer = new TMemoryStream;
}
__fastcall TcliForm::~TcliForm()
{
delete OutboxDataBuffer;
}
void __fastcall TcliForm::SendButtonClick(TObject *Sender)
{
if( (!ClientSocket->Active) || (!ClientSocket->Socket->Connected) )
return;
TFileStream *FS = new TFileStream( ExtractFilePath( ParamStr(0) ) +
"test.txt" );
try
{
int FileSize = FS->Size;
OutboxDataBuffer->Write(&FileSize, sizeof(int));
OutboxDataBuffer->CopyFrom(FS, FileSize);
}
__finally
{
delete FS;
if( OutboxDataBuffer->Size > 0 )
PostMessage(Handle, APPWM_SEND_DATA, 0, 0);
}
SendButton->Enabled = false;
}
void __fastcall TcliForm::ClientSocketWrite(TObject* Sender,
TCustomWinSocket* Socket)
{
if( OutboxDataBuffer->Size > 0 )
PostMessage(Handle, APPWM_SEND_DATA, 0, 0);
}
void __fastcall TcliForm::WndProc(TMessage &Message)
{
if( Message.Msg == APPWM_SEND_DATA )
{
int Size = OutboxDataBuffer->Size;
int NumberOfBytesSent = SendData(OutboxDataBuffer->Memory,
Size);
if( NumberOfBytesSent > 0 )
{
if( NumberOfBytesSent == Size )
OutboxDataBuffer->Clear();
else
{
LPBYTE pSource = ( ((LPBYTE)OutboxDataBuffer->Memory) +
NumberOfBytesSent );
int NumberOfBytesLeft = (Size-NumberOfBytesSent);
::MoveMemory(OutboxDataBuffer->Memory, pSource,
NumberOfBytesLeft);
OutboxDataBuffer->Size = NumberOfBytesLeft;
}
Size = OutboxDataBuffer->Size;
}
if( Size == 0 )
SendButton->Enabled = true;
}
else
TForm::WndProc(Message);
}
int __fastcall TcliForm::SendData(void* Buffer, int BufSize)
{
LPBYTE pBuffer = (LPBYTE) pBuffer;
int TotalSent = 0;
try
{
while( TotalSent < BufSize )
{
int NumberOfBytesSent =
ClientSocket->Socket->SendBuf(&pBuffer[TotalSent], BufSize-TotalSent);
if( NumberOfBytes == -1 )
break;
TotalSent += NumberOfBytes;
}
}
catch(const Exception &) { }
return TotalSent;
}
Gambit
Technical Details
Message-ID:
<41586fe3$1@newsgroups.borland.com>Path:
arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news.glorb.com!fr.ip.ndsoftware.net!newsfeed00.sul.t-online.de!t-online.de!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mailReferences:
<415856d5@newsgroups.borland.com>Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,b3058d6528d1daa1 X-Google-Attributes: gid11508e,public X-Google-Language: ENGLISH,ASCII-7-bit From: "Remy Lebeau \(TeamB\)" <no.spam@no.spam.com> Newsgroups: borland.public.cppbuilder.internet.socket References: <415856d5@newsgroups.borland.com> Subject: Re: Client: ctNonBlocking -> Server: stThreadBlocking Date: Mon, 27 Sep 2004 12:54:15 -0700 Lines: 171 X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2800.1409 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1409 NNTP-Posting-Host: 68.69.17.41 Message-ID: <41586fe3$1@newsgroups.borland.com> X-Trace: newsgroups.borland.com 1096314851 68.69.17.41 (27 Sep 2004 12:54:11 -0700) Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news.glorb.com!fr.ip.ndsoftware.net!newsfeed00.sul.t-online.de!t-online.de!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail