mina-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Emmanuel Lécharny <elecha...@gmail.com>
Subject Re: Controlling lock operation inside the session.write() method
Date Sat, 16 Feb 2013 15:15:52 GMT
Le 2/16/13 2:30 PM, Ricardo Cristian Ramirez a écrit :
> On Saturday, February 16, 2013 12:02:21 AM Emmanuel Lécharny wrote:
>
>> What exactly do you want to do ? Is this interrupting some sending if a
>> message is received from the server ?
> I am trying to send a message only once to the server but it seems
> impossible
> in the scope of non-blocking communication and my enable/disable conditions.
You have to define a stateful protocol to handle such conditional
communications.

In other words, and this is totally orthogonal to the blocking or non
blocking IO, your client must know if it can send a message, and the
server must tell the client about this possibility.

One possibility is to have a client blocked untl it receives an ACK from
the server. Here is a possible protocol :

Initial state
-------------
Client : can send
Server : can receive


Normal state
------------
(1) client : send message, switch to 'wait for ACK' (cannot send an
other message until this ACK is received)
...
(some delay)
...
(2) server : receive the message, send a ACK to the client
...
(some delay)
...
(3) client : receive the server's ACK, switch to 'can send a message'


And now, you can iterate to (1)


>
> Assume receiver thread takes the processor from sender thread before
> sending
> is not completed. And, receiver takes a disable message:
>
> Checking the client state before write() method may cause a missing
> message:
> Client writes message to the session. Receiver thread takes the processor.
> Receiver takes a disable message. When, the sender has the processor again,
> it
> sends the message but server does not take into account a client's message
> after disabling it. However, client thinks that the message has been sent.
> if(state==sending_enabled):
>     session.write(...)
The message can be considered as sent by the client when the
'MessageSent' event is fired. This event means the data has been fully
flushed into the socket.

Now, checking that is totally irrelevant in your scenario : you *can't*
- I mean, you really can't - know if the server has received the
message, unless the server has sent you an aknowledge. For that, the
server has to receive the message and send a response (see the protocol
above).

Eveything else (the threads reading or wraiting , whatsoever) is just
irrelevant.

Just consider that when you ave session.write() the message from the
client side, then the client has to wait for a response from the server,
and it has to be a message, not something like a messageSent event. This
has to be present in your high level protocol, whatever the
communication layer you are using (TCP, UDP, etc). That also mean that
your server must send a message when it has received a full message from
the client.

This is really simple.

>
> Checking the client state after write() method may cause duplication:
> Client
> writes message to the session and waits for the completion. After
> completion,
> receiver thread takes the processor between two if statement below.
> Receiver
> takes a disable message. Then, sender thread takes the processor again.
> Checks
> the state and resends the messages for second time.
> FutureWriter fWriter = session.write(...)
> fWriter.join()
> if(fWriter.isWritten()):
>     if(state==sending_disabled):
>         mark this message as not send. try to send again when sending
> enabled

You are trying to do some post-mortem control. It does not work, period.
Do it the other way : send a message when you know you can :
- either when the client connects for the first time
- or when you have actually received the server's response

In any other case, you should be in a non-transmitting state.

If you never receive a response from the server, then you should
consider either that the conneciton has been brutally closed from the
server side, or that the server is buggy. In any case, close the session
and inform the user.
>
>                                                 - o -
>
> On the other hand, interrupting the sending queue after taking a disable
> message may cause a loss too. Consider the following code:
> messageReceived(message):
>     if(message==sending_disabled):
>         list = session.getSendingQueue()
>         session.cancelSendingQueue()
>         addToResendList(list)
>
> Receiver takes a disable message and tries to cancel sending queue. Before
> canceling (calling cancelSendingQueue()), sender thread gains the processor
> and sends the message. Now, client thinks the message has been sent but
> server
> has just ignored it. Message is lost.

One more thing : if your server may send a 'sending_disable' message at
any time, then you have no way to guarantee that this message will be
processed corectly on the client side. At best, if the server send you
such a message then it should consider that any message it will receive
from the client is invalid (just because such a message might have been
sent before the server sent its 'disable-sending' message). Or you can
consider that the server will accept the client message, assuming that
the client has sent it *before* it recived the 'disable-sending'
message. That's also a legitimate choice.

But again, this is something you should design in your protocol, and the
way MINA works is really totally orthogonal.

Note that using Blocking IO does not solve any of the issue you have :
just because you have written some data in a socket does not mean the
server has received those data. In fact, you can *at the same time* have
the client and the server sending some data to each other (this is a
full duplex communication). The only way to solve this issue is to remap
some high level protocol on top of the low mevel protocol to manage such
situations.

Hope it helps.


-- 
Regards,
Cordialement,
Emmanuel Lécharny
www.iktek.com 


Mime
View raw message