Article View: borland.public.cppbuilder.internet.socket
Article #5263Re: Client: ctNonBlocking -> Server: stThreadBlocking
From: Vladimir Stefanovic
Date: Mon, 27 Sep 2004 20:14
Date: Mon, 27 Sep 2004 20:14
202 lines
6730 bytes
6730 bytes
What can I say than thanks for the detailed explanation with
full source code included. I'll try this tomorrow cos I do not
have BCB on this machine.
Best regards,
Vladimir Stefanovic
Remy Lebeau (TeamB) <no.spam@no.spam.com> wrote in message
news:41586fe3$1@newsgroups.borland.com...
>
> "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
ileStream( 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:
<41587454@newsgroups.borland.com>Path:
arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news.glorb.com!news.zanker.org!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mailReferences:
<415856d5@newsgroups.borland.com> <41586fe3$1@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: "Vladimir Stefanovic" <spam@not.needed> Newsgroups: borland.public.cppbuilder.internet.socket References: <415856d5@newsgroups.borland.com> <41586fe3$1@newsgroups.borland.com> Subject: Re: Client: ctNonBlocking -> Server: stThreadBlocking Date: Mon, 27 Sep 2004 22:14:29 +0200 Lines: 204 X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 5.00.2314.1300 X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2314.1300 NNTP-Posting-Host: 213.137.116.181 Message-ID: <41587454@newsgroups.borland.com> X-Trace: newsgroups.borland.com 1096315988 213.137.116.181 (27 Sep 2004 13:13:08 -0700) Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news.glorb.com!news.zanker.org!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail