Hi all,
I'm using the TTcpClient class in C++Builder XE2.
As soon as I set the Active property to true, I can trace (via wireshark) the TCP syn/syn ack sequence.
This tells me that there IS a TCP connection active. The connected property however always indicates false.
if( TcpClient == NULL)
TcpClient = new TTcpClient(NULL); // Now own TcpClient
DWORD CIpIo::Open(int DeviceNumber, HDEVINFO DeviceList, const GUID* InterfaceGuid)
{
if( !IPClient->Active) {
IPClient->Active = true;
Sleep(250); // Give TSEC server time to stack it's protocols....
}
return(0);
}
Any suggestions?
Thanx....
#TTcpClient #builder
rene wrote:
> But indeed a disconnect event isn't fired eventhough there's a FIN sequence.
TTcpClient and TTcpServer are not event-driven components, even in non-blocking
mode. The only time the TTcpClient.OnDisconnect event is fired is when TTcpClient.Close()
is called. And in fact, in non-blocking mode, it would never fire OnDisconnect
anyway because it depends on the Connected property being true, and as I
mentioned earlier, Connected is never set to true in non-blocking mode.
> Is there a better solution in XE7
Use a different component.
> are the Indy components in XE2 any better?
MUCH MUCH better. If you don't want to use Indy, and if you are only targetting
Windows, you could always install Embarcadero's dclSockets... package to
enable the older TClientSocket/TServerSocket components. They are vastly
more usable than TTcpClient/TTcpServer. But if you need cross-platform support,
Indy is your best choice, unless you decode to use another third-party cross-platform
library.
--
Remy Lebeau (TeamB)
rene wrote:
> I'm using the TTcpClient class in C++Builder XE2.
I strongly recommend against using TTcpClient (or TTcpServer). One, because
it is a horribly written component that is very difficult to use effectively.
Two, because it is a dead component, deprecated and removed from the product
in XE6.
> As soon as I set the Active property to true, I can trace (via
> wireshark) the TCP syn/syn ack sequence.
>
> This tells me that there IS a TCP connection active. The connected
> property however always indicates false.
Did you, by chance, set the BlockMode property to bmNonBlocking? If so,
the Connected property will NEVER be set to true.
The ONLY time that Connected gets set to true is inside of TCustomIpClient::Open()
when the socket API connect() function returns success immediately. In non-blocking
mode, that will never happen, as connect() always fails with a (WSA)EWOULDBLOCK
error instead. TTcpClient DOES NOT take that into account, so it does not
know when a non-blocking connect() has finished its work or whether it succeeded/failed.
You can, however, account for that manually in your own code:
{code}
private:
int LastSocketError;
....
if( TcpClient == NULL)
{
TcpClient = new TTcpClient(NULL); // Now own TcpClient
TcpClient->OnError = &TcpClientError;
}
....
void __fastcall CIpIo::TcpClientError(TObject *Sender, int SocketError)
{
LastSocketError = SocketError;
}
DWORD CIpIo::Open(int DeviceNumber, HDEVINFO DeviceList, const GUID* InterfaceGuid)
{
if (!IPClient->Active)
{
LastSocketError = 0;
IPClient->Active = true;
if (!IPClient->Active)
{
// error creating the socket
return ...;
}
if (!IPClient->Connected)
{
if (LastSocketError != WSAEWOULDBLOCK)
{
// error connecting to server
IPClient->Active = false;
return ...;
}
// non-blocking connect, wait for result...
bool Writable = false;
if (!IPClient->Select(NULL, &Writable, NULL, 5000))
{
// not connected
IPClient->Active = false;
return ...;
}
}
// connected to server
Sleep(250); // Give TSEC server time to stack it's protocols....
}
return 0;
}
{code}
--
Remy Lebeau (TeamB)