I have some strage behaviour of SNMP4J which I can't explain. It is likely is due to my misunderstanding of snmp basics.
I deal with server which receives snmp traps. Everything is going on well. Now I need to change traps to inform.
The issue is my server is trying to handle received message twice. I occured with duplicating of INFORM message.
Trying to explain... I've enabled logger to DEBUG level.
When INFORM is arrived I see in log file two same records from class org.snmp4j.transport.DefaultUdpTransportMapping.ListenThread which has following code in run() method:
if (logger.isDebugEnabled()) {
logger.debug("Received message from "+packet.getAddress()+"/"+
packet.getPort()+
" with length "+packet.getLength()+": "+
new OctetString(packet.getData(), 0,
packet.getLength()).toHexString());
}
Also I have class which implements interface org.snmp4j.CommandResponder. His method void processPdu(CommandResponderEvent event) is invoked twice for inform and once for a trap.
#Override
public void processPdu(final CommandResponderEvent evt) {
final Address address = getAgentAddress(evt);
final PDU command = evt.getPDU();
boolean isInform = command.getType() == PDU.INFORM // this is true for both invocations of this method while receiving INFORM
}
Details about versions:
snmp v2, snmp4j version 2.3.0
Help me to realize: Does exist some bug here of I should filter second invocation of processPdu method by command.getRequestID(), for example?
The INFORM must be acknowledged by Receiver.
I believe the problem is that the sender have not received the RESPONSE PDU back for this INFORM REQUEST for some reason. So it sends it once again according to the number of retries. Make sure you send RESPONSE PDU to the sender to confirm that you've received REQUEST PDU (INFORM). The API should do it for you. So make sure you call the default handler.
Related
I am using Java EWS API to send a mail using SendandSaveCopy. I want to put a checker if the mail was sent successfully or not (in case the internet was not working). When I try to do that, it shows that it is a void method. is there any way to find out whether the mail was sent successfully.
in EmailMessage class, use method setIsDeliveryReceiptRequestedand set to true before you send the mail.
Once the mail is sent and the messaging server has delivered the mail to recipient, you will receive a message (if supported by the messaging server) reporting when the recipient has received the message.
/**
* Sets the checks if is delivery receipt requested.
*
* #param value the new checks if is delivery receipt requested
* #throws Exception the exception
*/
public void setIsDeliveryReceiptRequested(Boolean value) throws Exception {
this.getPropertyBag().setObjectFromPropertyDefinition(
EmailMessageSchema.IsDeliveryReceiptRequested, value);
}
https://github.com/OfficeDev/ews-java-api/blob/master/src/main/java/microsoft/exchange/webservices/data/core/service/item/EmailMessage.java#L437
DOC from official API
The Message object contains two properties that can direct the underlying MAPI system to report successful receipt of the message: DeliveryReceipt and ReadReceipt.
When you set these properties to True and send the message, the underlying MAPI system automatically tracks the message for you. When you set the DeliveryReceipt property, the MAPI system automatically generates a message to the sender reporting when the recipient receives the message. When you set the ReadReceipt property, the MAPI system automatically generates a message to the sender reporting when the recipient reads the message.
https://msdn.microsoft.com/en-us/library/ms526415(v=exchg.10).aspx
You can also use ReadReceipt to know when the message has been read.
The only reliable way I've found to do this is to start polling the item afterwards to see when the changekey arrives, indicating that it got processed. Details here:
In Office.js, How do we use the Office.context.mailbox.item.saveAsync response (overcoming ErrorItemNotFound)?
Note that you'll typically get a number of failures over the first few seconds before it finally works - be sure your polling loop knows how to prepare for that.
I'm reading the akka documentation and now I'm at the section about Inbox. Here's what is said there:
The send method wraps a normal tell and supplies the internal actor’s
reference as the sender.
But what's the difference? When using tell this way:
ActorRef aRef1;
ActorRef aRef2;
//init the references
aRef1.tell(aRef2, "Message");
we can get the sender in the onRecieve method like this:
public void onReceive(Object message) throws Exception {
System.out.println("Sender: " + getSender().path().name());
}
What's the actual benefit of send in comparison to just tell?
The purpose of an Inbox is to have
an actor-like object which is interrogated from the outside.
It's not meant to be used within an actor. It's for external systems that have access to the actor system/context and want to send a message to an actor.
The method send documentation states
Have the internal actor act as the sender of the given message which
will be sent to the given target. This means that should the target
actor reply then those replies will be received by this Inbox.
This allows an external component to act as if it was part of the actor system and receive messages from actors. Unfortunately, the price to pay for this is that receive is blocking.
Regarding Java NIO2.
Suppose we have the following to listen to client requests...
asyncServerSocketChannel.accept(null, new CompletionHandler <AsynchronousSocketChannel, Object>() {
#Override
public void completed(final AsynchronousSocketChannel asyncSocketChannel, Object attachment) {
// Put the execution of the Completeion handler on another thread so that
// we don't block another channel being accepted.
executer.submit(new Runnable() {
public void run() {
handle(asyncSocketChannel);
}
});
// call another.
asyncServerSocketChannel.accept(null, this);
}
#Override
public void failed(Throwable exc, Object attachment) {
// TODO Auto-generated method stub
}
});
This code will accept a client connection process it and then accept another.
To communicate with the server the client opens up an AsyncSocketChannel and fires the message.
The Completion handler completed() method is then invoked.
However, this means if the client wants to send another message on the same AsyncSocket instance it can't.
It has to create another AsycnSocket instance - which I believe means another TCP connection - which is performance hit.
Any ideas how to get around this?
Or to put the question another way, any ideas how to make the same asyncSocketChannel receive multipe CompleteionHandler completed() events?
edit:
My handling code is like this...
public void handle(AsynchronousSocketChannel asyncSocketChannel) {
ByteBuffer readBuffer = ByteBuffer.allocate(100);
try {
// read a message from the client, timeout after 10 seconds
Future<Integer> futureReadResult = asyncSocketChannel.read(readBuffer);
futureReadResult.get(10, TimeUnit.SECONDS);
String receivedMessage = new String(readBuffer.array());
// some logic based on the message here...
// after the logic is a return message to client
ByteBuffer returnMessage = ByteBuffer.wrap((RESPONSE_FINISHED_REQUEST + " " + client
+ ", " + RESPONSE_COUNTER_EQUALS + value).getBytes());
Future<Integer> futureWriteResult = asyncSocketChannel.write(returnMessage);
futureWriteResult.get(10, TimeUnit.SECONDS);
} ...
So that's it my server reads a message from the async channe and returns an answer.
The client blocks until it gets the answer. But this is ok. I don't care if client blocks.
Whent this is finished, client tries to send another message on same async channel and it doesn't work.
There are 2 phases of connection and 2 different kind of completion handlers.
First phase is to handle a connection request, this is what you have programmed (BTW as Jonas said, no need to use another executor). Second phase (which can be repeated multiple times) is to issue an I/O request and to handle request completion. For this, you have to supply a memory buffer holding data to read or write, and you did not show any code for this. When you do the second phase, you'll see that there is no such problem as you wrote: "if the client wants to send another message on the same AsyncSocket instance it can't".
One problem with NIO2 is that on one hand, programmer have to avoid multiple async operations of the same kind (accept, read, or write) on the same channel (or else an error occur), and on the other hand, programmer have to avoid blocking wait in handlers. This problem is solved in df4j-nio2 subproject of the df4j actor framework, where both AsyncServerSocketChannel and AsyncSocketChannel are represented as actors. (df4j is developed by me.)
First, you should not use an executer like you have in the completed-method. The completed-method is already handled in a new worker-thread.
In your completed-method for .accept(...), you should call asychSocketChannel.read(...) to read the data. The client can just send another message on the same socket. This message will be handled with a new call to the completed-method, perhaps by another worker-thread on your server.
say you have multiple agents(each of them is it's own process) which can communicate to each other(agents communicate only in pairs); how do you ensure that once two agents start communicating, no other agent can interrupt them?
Here's the important part of the code:
class Agent {
private void send(int to, byte[] message) {...};
private void receive(int from, byte[] message) {...};
}
The send method sends the message to the specified agent and receive method processes the received message, that comes from other agents. So let's say agents with id=1 and id=2 exchange a few messages: how do I ensure that neither of the agents processes(in it's receive method) messages from any other agent during their exchange? I tried filtering messages based on agent's id(by storing them in int variable) but it doesn't seems to work properly?
With processes and using TCP for the IPC, at any time let every agent have at most one socket open. Then a second agent will never be able to talk with an already talking agent.
You can give receivers a token. When an agent want to send to a receiver, it should get the receiver's token at first. After finishing the whole communication, the sender will release the token, and then other's can send to the receiver.
I'm creating an instant messaging client using Smack 3.1.0 and Java. The problem I'm running in to has to do with sending messages to the user on a specific domain.
For example, I have two users, 1#gmail.com and 2#gmail.com. 1#gmail.com logs in to XMPP through my IM client. 2#gmail.com logs in to GChat through gmail.com AND a second time through pidgin. So now I have one instance of 1#gmail.com and 2 instances of 2#gmail.com.
The way gmail works, if 1#gmail.com sends a message to 2#gmail.com, the gmail and the pidgin client both get the initial message. But then if the gmail instance responds to the message, every message from then on only goes between 1#gmail.com and the gmail instance of 2#gmail.com.
I would like to mimic this behavior with my IM client. I would think the way to do it would be to set up a Chat, send the initial IM to all instances of the recipient. Then I'd set up a MessageListener to listen for a response. When I get the response, I'd have to create a new chat, specifying the 2#gmail.com/resource. But then I'd have to write the MessageListener twice. Any ideas? Here's some sample code that I'm using (the method AddText() simply appends the message to my conversation pane):
recipient = buddy;
setTitle("Instant Message - "+recipient);
chat = com.andreaslekas.pim.PIM.connection.getChatManager().createChat(recipient.getUser(), new MessageListener() {
public void processMessage(Chat chat, Message msg) {
//if(chat.getParticipant().indexOf('/')!=-1)
addText(msg.getBody(), chat.getParticipant(), true);
}
});
UPDATE
I wanted to supplement the answer below with actual code that I used to make this work:
chat = com.andreaslekas.pim.PIM.connection.getChatManager().createChat(recipient.getUser(), new MessageListener() {
public void processMessage(Chat new_chat, Message msg) {
if(msg.getFrom().replaceFirst("/.*", "").equals(recipient.getUser()))
{
if(buddy_resource==null || !msg.getFrom().replaceFirst(".*?/", "").equals(buddy_resource.getResource()))
{
buddy_resource = recipient.getResource(msg.getFrom().replaceFirst(".*?/", ""));
chat = null;
chat = com.andreaslekas.pim.PIM.connection.getChatManager().createChat(recipient.getUser()+"/"+buddy_resource.getResource(), new MessageListener(){
public void processMessage(Chat new_chat2, Message msg) {
addText(msg.getBody(), new_chat2.getParticipant(), true);
}
});
}
addText(msg.getBody(), chat.getParticipant(), true);
}
}
});
To summarize, I send the first message to all resources of the recipient's address and wait for a response. When I get the response, I replace the current Chat object with a new one that specifies the individual resource that responded to the initial message. The code is a little messy with two different MessageListener objects that could probably be combined into a new class. But it works.
So far I understood Message Carbon (XEP - 0280) will solve your problem.
If you enable carbon it will distribute messages to all logged resources of a user. In your case if 1#gmail.com send message to 2#gmail.com it will be distributed to all logged resources of 2#gmail.com.
Here's a code sample using smack,
CarbonManager cm = CarbonManager.getInstanceFor(connection);
cm.enableCarbons();
cm.sendCarbonsEnabled();
First make sure that your server is supported Message Carbon.
Then send message as usual.
In your MessageListener why not always respond to the sender? I think you get it by calling something like msg.getSender() or getFrom() (I'm on mobile right now, cannot check)