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