Board index » delphi » Sending/Receiving from within Socket OnConnect Events ?

Sending/Receiving from within Socket OnConnect Events ?

Hello group,

Is it possible to Send or Receive data from within the OnConnect Events
of Delphi TServer/TClient Sockets ???

I have developed a client/server communication app that works using this
method, but not always.

I am trying to develop a user password check before Accepting a connection
from
the Client to the Server. Delphi Docs state that the OnAccept event occurs
before
the OnConnect Event, but it is not correct (or is it  ?)

** What is best method for checking user before allowing Socket Connection
??

Here is code snippit:
CLIENT APPLICATION
{Username/Password is sent from within the ClientConnect Event.}

procedure TFClient.TCPClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
type
TLoginDetails = record
 Username: string[32];
 Password: string[32];
 end;
var
LoginDetails: TLoginDetails;
MS: TMemoryStream;
begin
LoginDetails.Password := 'demo';
LoginDetails.Username := 'demo';
MS := TMemoryStream.Create;
MS.Write(LoginDetails, SizeOf(LoginDetails));
MS.Position := 0;
Socket.SendStream(MS); { stream will be freed by socket }
end;

SERVER APPLICATION
{Username/Password is checked from within the ServerClientConnect Event.}

procedure TFServer.TCPserverClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
type
TLoginDetails = record
 Username: string[32];
 Password: string[32];
 end;
var
MsgBuf: string;
MsgLen,LenReceived : integer;
LoginDetails: TLoginDetails;
begin
MsgLen := Socket.ReceiveLength;
if MsgLen = 0 then begin
   { INVALID LOGIN }
   Socket.Close;
   exit;
   end;
if TCPServer.Socket.ActiveConnections >= 2 then begin
   { ONLY ALLOW ONE CONNECTION }
   Socket.Close;
   exit;
   end;
TRY
SetLength(MsgBuf, MsgLen);
LenReceived := Socket.ReceiveBuf(MsgBuf[1], MsgLen);
MsgBuf := Copy(MsgBuf, 1, LenReceived);
if Length(MsgBuf) = SizeOf(LoginDetails) then begin { LOGINDETAILS = 66
bytes}
   move(MsgBuf[1], LoginDetails, SizeOf(LoginDetails));
   Delete(MsgBuf, 1, SizeOf(LoginDetails));
   if LoginDetails.Password = LoginPassword then SendMsg(MSG_LOGIN_OK,
'Password Accepted', Socket)
   else begin
        SendMsg(MSG_LOGIN_FAIL, 'Invalid Password', Socket);
        socket.Close;
        exit;
        end;
   end else begin
   { INVALID LOGIN }
   Socket.Close;
   end;
EXCEPT
{ServerLog.Lines.Add('EXCEPTION LOGIN: '+SysErrorMessage(GetLastError));}
Socket.Close;
END;
end;

 

Re:Sending/Receiving from within Socket OnConnect Events ?


"Carl" <mail2carl@_remove_yahoo.com> schreef in bericht
news:3c986c07$1_1@dnews...

Quote
> Hello group,

> Is it possible to Send or Receive data from within the OnConnect Events
> of Delphi TServer/TClient Sockets ???

Assuming non-blocking sockets:
In the Client OnConnect(), sending:yes, receiving:no
In the Server OnConnect(), sending:no, receiving:yes

Quote
> I am trying to develop a user password check before Accepting a connection
> from the Client to the Server. Delphi Docs state that the OnAccept event
occurs
> before the OnConnect Event, but it is not correct (or is it  ?)

This is only correct for blocking server sockets .

Quote
> ** What is best method for checking user before allowing Socket Connection

Setting up a socket connection is a 3-way handshake.
Client                 Server
        ====SYN=====>
Connect!<==ACK,SYN===
        ==ACK + DATA=>  Connect!, now server can send data

So the server can only send data when the connection is fully established.
Imho, the simplest way to implement a password scheme, would be that the
client is  required to send his password/name/whatever as his first message.
This message can be transmitted in the client's OnConnect() handler.
If the server - in his OnConnect()handler - determines that the client must
be denied access, it simply closes the socket. ( Just do Socket.Close )

--
Regards,

Dirk Claessens
---------------------------------------------------------
http://users.pandora.be/dirk.claessens2
Attention: All spamshields raised; E-mails will bounce!
---------------------------------------------------------

Re:Sending/Receiving from within Socket OnConnect Events ?


Only one sending via Client to Server. I have setup the OnConnect Events
(See my Code in last message) but when the OnClientConnect event on
the server starts it usually receives 0 Data when I try the ReceiveBuf or
ReceiveText functions. It then goes on to the next Event OnAccept.

Carl.

Is the ClientSocket.Socket.Data available at the Server end in
ServerSocket.Socket.Data ??

Quote
"Dirk Claessens" <will.bounce@invalid> wrote in message

news:3c98ebac$1_1@dnews...
Quote

> "Carl" <mail2carl@_remove_yahoo.com> schreef in bericht
> news:3c986c07$1_1@dnews...
> > Hello group,

> > Is it possible to Send or Receive data from within the OnConnect Events
> > of Delphi TServer/TClient Sockets ???

> Assuming non-blocking sockets:
> In the Client OnConnect(), sending:yes, receiving:no
> In the Server OnConnect(), sending:no, receiving:yes

> > I am trying to develop a user password check before Accepting a
connection
> > from the Client to the Server. Delphi Docs state that the OnAccept event
> occurs
> > before the OnConnect Event, but it is not correct (or is it  ?)

> This is only correct for blocking server sockets .

> > ** What is best method for checking user before allowing Socket
Connection

> Setting up a socket connection is a 3-way handshake.
> Client                 Server
>         ====SYN=====>
> Connect!<==ACK,SYN===
>         ==ACK + DATA=>  Connect!, now server can send data

> So the server can only send data when the connection is fully established.
> Imho, the simplest way to implement a password scheme, would be that the
> client is  required to send his password/name/whatever as his first
message.
> This message can be transmitted in the client's OnConnect() handler.
> If the server - in his OnConnect()handler - determines that the client
must
> be denied access, it simply closes the socket. ( Just do Socket.Close )

> --
> Regards,

> Dirk Claessens
> ---------------------------------------------------------
> http://users.pandora.be/dirk.claessens2
> Attention: All spamshields raised; E-mails will bounce!
> ---------------------------------------------------------

Re:Sending/Receiving from within Socket OnConnect Events ?


"Carl" <mail2carl@_remove_yahoo.com> schreef in bericht
news:3c98f7ce_2@dnews...

Quote
> Only one sending via Client to Server. I have setup the OnConnect Events
> (See my Code in last message) but when the OnClientConnect event on
> the server starts it usually receives 0 Data when I try the ReceiveBuf or
> ReceiveText functions. It then goes on to the next Event OnAccept.

> Carl.

I've spotted the error now.
You cannot call Socket.ReceiveBuf() in the OnConnect() handler; You need to
do that in the OnRead() handler! That's how non-blocking sockets work.

--
Regards,

Dirk Claessens
---------------------------------------------------------
http://users.pandora.be/dirk.claessens2
Attention: All spamshields raised; E-mails will bounce!
---------------------------------------------------------

Re:Sending/Receiving from within Socket OnConnect Events ?


I have used another alternate method now. It seems to me that both
Client and Server need to be fully connected and the only way to send
data both ways successfully is to use the OnRead events.

I can only validate a users IP address and Close the Socket from the servers
OnConnect or OnAccept events. It's Not possible to check a password sent
from the Client from within these events. :-(

Thanks for your help all the same.

Carl.

Quote
"Dirk Claessens" <will.bounce@invalid> wrote in message

news:3c9a362b$1_1@dnews...
Quote

> "Carl" <mail2carl@_remove_yahoo.com> schreef in bericht
> news:3c98f7ce_2@dnews...
> > Only one sending via Client to Server. I have setup the OnConnect Events
> > (See my Code in last message) but when the OnClientConnect event on
> > the server starts it usually receives 0 Data when I try the ReceiveBuf
or
> > ReceiveText functions. It then goes on to the next Event OnAccept.

> > Carl.

> I've spotted the error now.
> You cannot call Socket.ReceiveBuf() in the OnConnect() handler; You need
to
> do that in the OnRead() handler! That's how non-blocking sockets work.

> --
> Regards,

> Dirk Claessens
> ---------------------------------------------------------
> http://users.pandora.be/dirk.claessens2
> Attention: All spamshields raised; E-mails will bounce!
> ---------------------------------------------------------

Re:Sending/Receiving from within Socket OnConnect Events ?


But you can simply use a flag for a client that indicates if a password has
already been sent.
If not, you simply deny any request the client makes.

andy

--
Kyoto Now !

Re:Sending/Receiving from within Socket OnConnect Events ?


Yes, that what I am doing.

If not Client Authenticated then Check Login Details.
If Login Details Fail then Close Connection.

Quote
"Andy M." <andy.mail...@gmx.net> wrote in message news:3c9b13ba_2@dnews...
> But you can simply use a flag for a client that indicates if a password
has
> already been sent.
> If not, you simply deny any request the client makes.

> andy

> --
> Kyoto Now !

Re:Sending/Receiving from within Socket OnConnect Events ?


Quote
"Carl" <mail2carl@_remove_yahoo.com> wrote in message

news:3c986c07$1_1@dnews...

Quote
> Hello group,

> Is it possible to Send or Receive data from within the OnConnect Events
> of Delphi TServer/TClient Sockets ???

Assuming Non blocking
Write in the OnConnect event? No, dont do it. You cant always rely on status
of the socket.
After socket connects, wait till you receive the OnWrite event that tells
you socket is changing from 'not able to write' to being 'able to write'.

Regarding reading., that would depend on whether the other side of
connection has sent data. Wait for the OnRead event to flag there's data
waiting at the socket. Note - you may keep getting onread events if you dont
read all the received data in a single chunk.

To handle non-blocking winsock sockets you really need a State Engine so
that you can perform waits at the appropriate moments. Basically you'll need
to wait for
1) OnWrite events when you open the socket or whenever you receive -1 result
when attempting to write data to the socket.
2) OnRead events when you're waiting for data arriving from the other end of
connection

In between times, you have to be able to handle the OnDisconnect,
OnSocketError events gracefully , and use some kind of timeout for the wait
periods.

For my company Ive written a generic layer over TCustomWinSocket that acts
as a state engine.  We too perform authorization procedures on connections.
The engine is in one of 4 states, 'disconnected', 'idle', 'perfoming'
conversation or 'disconnecting'. It changes from disconnected to idle when
the socket has connected and the OnWrite event has been received. When I
attempt to disconnect the socket, I set the state to Disconnecting until I
receive the OnDisconnect event. Idle means the socket is free to perform a
conversation. 'Performing' conversation means the socket is busy with the
top level in-house protocol.
If you use a state engine, you would wait for the onconnect event, then set
a flag to say that authorization is required. When you receive the OnWrite
event you would then perform the authorization transaction. If that fails,
you then disconnect the socket.
In our case each conversation/top level protocol is handled as individual
transaction objects that are created as requests are made of the socket by
entry functions. The results are returned in callback events when the
transactions objects are freed.

Quote

> I have developed a client/server communication app that works using this
> method, but not always.

> I am trying to develop a user password check before Accepting a connection
> from
> the Client to the Server. Delphi Docs state that the OnAccept event occurs
> before
> the OnConnect Event, but it is not correct (or is it  ?)

> ** What is best method for checking user before allowing Socket Connection
> ??

> Here is code snippit:
> CLIENT APPLICATION
> {Username/Password is sent from within the ClientConnect Event.}

> procedure TFClient.TCPClientConnect(Sender: TObject;
>   Socket: TCustomWinSocket);
> type
> TLoginDetails = record
>  Username: string[32];
>  Password: string[32];
>  end;
> var
> LoginDetails: TLoginDetails;
> MS: TMemoryStream;
> begin
> LoginDetails.Password := 'demo';
> LoginDetails.Username := 'demo';
> MS := TMemoryStream.Create;
> MS.Write(LoginDetails, SizeOf(LoginDetails));
> MS.Position := 0;
> Socket.SendStream(MS); { stream will be freed by socket }
> end;

> SERVER APPLICATION
> {Username/Password is checked from within the ServerClientConnect Event.}

> procedure TFServer.TCPserverClientConnect(Sender: TObject;
>   Socket: TCustomWinSocket);
> type
> TLoginDetails = record
>  Username: string[32];
>  Password: string[32];
>  end;
> var
> MsgBuf: string;
> MsgLen,LenReceived : integer;
> LoginDetails: TLoginDetails;
> begin
> MsgLen := Socket.ReceiveLength;
> if MsgLen = 0 then begin
>    { INVALID LOGIN }
>    Socket.Close;
>    exit;
>    end;
> if TCPServer.Socket.ActiveConnections >= 2 then begin
>    { ONLY ALLOW ONE CONNECTION }
>    Socket.Close;
>    exit;
>    end;
> TRY
> SetLength(MsgBuf, MsgLen);
> LenReceived := Socket.ReceiveBuf(MsgBuf[1], MsgLen);
> MsgBuf := Copy(MsgBuf, 1, LenReceived);
> if Length(MsgBuf) = SizeOf(LoginDetails) then begin { LOGINDETAILS = 66
> bytes}
>    move(MsgBuf[1], LoginDetails, SizeOf(LoginDetails));
>    Delete(MsgBuf, 1, SizeOf(LoginDetails));
>    if LoginDetails.Password = LoginPassword then SendMsg(MSG_LOGIN_OK,
> 'Password Accepted', Socket)
>    else begin
>         SendMsg(MSG_LOGIN_FAIL, 'Invalid Password', Socket);
>         socket.Close;
>         exit;
>         end;
>    end else begin
>    { INVALID LOGIN }
>    Socket.Close;
>    end;
> EXCEPT
> {ServerLog.Lines.Add('EXCEPTION LOGIN: '+SysErrorMessage(GetLastError));}
> Socket.Close;
> END;
> end;

--
Clairebear

http://www.corkyscave.com

2.0.0 Beardies
1.1.0 Garter
0.0.2 Corn
1.0.0 Pueblan Milk
1.0.0 Cali King
1.2.0 Red tail
1.1.0 Hogg Island
1.0.0 Royal
1.1.0 Borneo {*word*76}
1.1.0 Carpet
1.1.0 Western Hognose

Re:Sending/Receiving from within Socket OnConnect Events ?


I've sorted it now by using the OnRead events instead.

Cheers for all the feedback everyone.

Carl.

Quote
"Dirk Claessens" <will.bounce@invalid> wrote in message

news:3c9a362b$1_1@dnews...
Quote

> "Carl" <mail2carl@_remove_yahoo.com> schreef in bericht
> news:3c98f7ce_2@dnews...
> > Only one sending via Client to Server. I have setup the OnConnect Events
> > (See my Code in last message) but when the OnClientConnect event on
> > the server starts it usually receives 0 Data when I try the ReceiveBuf
or
> > ReceiveText functions. It then goes on to the next Event OnAccept.

> > Carl.

> I've spotted the error now.
> You cannot call Socket.ReceiveBuf() in the OnConnect() handler; You need
to
> do that in the OnRead() handler! That's how non-blocking sockets work.

> --
> Regards,

> Dirk Claessens
> ---------------------------------------------------------
> http://users.pandora.be/dirk.claessens2
> Attention: All spamshields raised; E-mails will bounce!
> ---------------------------------------------------------

Other Threads