How should an snmp client receive responses from multiple snmp agents? - snmp

I require to send get requests/ receive responses to several snmp agents from a single client/manager process.
I have implemented client/agent based on below urls:
http://www.jitendrazaa.com/blog/java/snmp/create-snmp-client-in-java-using-snmp4j/ http://www.jitendrazaa.com/blog/java/snmp/creating-snmp-agent-server-in-java-using-snmp4j/
In order to send a request to an agent, the following is carried out for each server:
TransportMapping transport = new DefaultUdpTransportMapping();
snmp = new Snmp(transport);
transport.listen();
...
pdu.setType(PDU.GET);
// communityTarget contains server target address.
ResponseEvent event = snmp.send(pdu, communityTarget, null);
In order to receive responses from the servers, do I require to carry out a separate transport.listen() for each server? or create
a new TransportMapping and Snmp object for each server?
I don't understand how the client process can know which server returned the response? ...since
each time transport.listen() is called, the listening port address (transport.getListenAddress()) is the same.
and 1 extra udp port is listed (netstat).
I am intending to poll each server from a different background thread (in order that the polling interval can be configured).
Thank you

You should use the same transport mapping.
From the example you provided, it seems that you are using the synchronous API.
The response is just from the agent you sent the request too.
In any case, you can get the peer (agent) address from ResponseEvent.getPeerAddress
http://www.snmp4j.org/doc/org/snmp4j/event/ResponseEvent.html#getPeerAddress()

Related

Go HTTP idle connection pool and http trace

I have a long running GO program(version 1.18) which sends hundreds of GET requests simultaneously per second using RESTY to the remote https://api.abcd.com. Each GET request is a separate go-routine which uses the same RESTY client.
remote server https://api.abcd.com is nginx/1.19.2(HTTP/2), IP address is 11.11.11.11 and 22.22.22.22. Yes, this remoter server has multiple IP addresses.
I use hostname when setting RESTY client
SetBaseURL("https://api.abcd.com")
Transport configuration are default one in RESTY.
TraceInfo() is enabled on RESTY client side. There is a "IsConnReused" field in the trace info. This IsConnReused actually comes from struct GotConnInfo in GO httptrace package:
type GotConnInfo struct {
Conn net.Conn
// Reused is whether this connection has been previously used for another HTTP request.
Reused bool
// WasIdle is whether this connection was obtained from anidle pool.
WasIdle bool
// IdleTime reports how long the connection was previously idle, if WasIdle is true.
IdleTime time.Duration
}
question 1: GO httptrace determine "Connection reused" based on hostname(api.abcd.com) or IP address?
question 2: GO http package idle connection pool is actually a map, key is a struct type connectMethodKey. The addr field in this struct is hostname or IP address?
type connectMethodKey struct {
proxy, scheme, addr string
onlyH1 bool
}
This is what I found in TraceInfo(). When the program runs at the beginning, all requests are sent to 11.11.11.11:443. Few minutes later, all requests are sent to 22.22.22.22, no 11.11.11.11 anymore. Then, few minutes later, all requests start to sent to 11.11.11.11 again, no 22.22.22.22 this time.
question 3: when requests start to sent to 22.22.22.22, the socket connections to 11.11.11.11 are idle, why GO http does not use idle connections anymore? I don't think those idle connection has already timeout.
question 1: GO httptrace determine "Connection reused" based on
hostname(api.abcd.com) or IP address?
httptrace.GotConnInfo.Reused tracks if TCP connection was used for another HTTP request. It is per IP address.
question 2: GO http package idle connection pool is actually a map,
key is a struct type connectMethodKey. The addr field in this struct
is hostname or IP address?
addr is hostname
Could be an IP though if you send request to something like http://127.0.0.1/.
question 3: when requests start to sent to 22.22.22.22, the socket
connections to 11.11.11.11 are idle, why GO http does not use idle
connections anymore? I don't think those idle connection has already
timeout.
It could work differently if you use HTTP 1.
With it, every request requires the own TCP connection. Subsequent requests may reuse TCP connection, but if you want to run requests in parallel, you need to establish multiple TCP connections. Every connection would use a different IP address, and you would see traffic evenly distributed.
With HTTP/2 a single TCP connection can be used for multiple parallel requests. That connection uses a single IP address.
This is how GO calculates if a new request can use open connection:
https://cs.opensource.google/go/x/net/+/69896b71:http2/transport.go;l=881;drc=69896b714898bee1e3403560cd2e1870bcc8bd35;bpv=1;bpt=1
Play with these prams to distribute the traffic across multiple TCP connections.

How to get the IP address of a connected WebSocket-client?

I'm currently working on a ABAP Push Channel server to WebSocket client connection and I need the IP-address of the client in order to identify whether this client is the one I want to send the message to. In my scenario there could be multiple WebSocket connections.
Now there is the ssi_websocket_table table and the ssi_websocket_table_row row with the the field caller_ip, however this gives me the IP address of the DNS-Server of the network I'm connected to, and I expected the IP address of my local PC since the WebSocket-client is running on this machine.
Is there any other way to get the clients IP address from an active WebSocket connection in ABAP?
P.S. Looking at all the table entries, it shows the correct IP when using a different server configuration, as soon as I know why that's the case I will report back.
As pointed out by vwegert it makes no sense to use the IP to tell the WebSockets apart, I think it would probably be better to use an ID for each WebSocket connection instead.
You could get the IP from the WebSocket server context which gets the IP header apparently from the opening HTTP handshake for the connection:
DATA(lo_context) = i_context. " IF_APC_WSP_SERVER_CONTEXT type
DATA(lo_request) = lo_context->get_initial_request( ).
" initialize G_CONTEXT_ID_FIELD for PCP_SET_CONTEXT_FIELDS
DATA(lv_id) = lo_request->get_header_field( if_http_header_fields_sap=>remote_addr ).
the sample is taken from the SAP standard class CL_APC_WS_EXT_ABAP_ONLINE_COMM, ON_MESSAGE method.

How to assign an SNMPv2c inform request from another manager to the proper agent?

The SNMPv2c specification states that "An InformRequest-PDU is generated and transmitted at the request of an application in a SNMPv2 entity acting in a manager role..." [RFC 1905, section 4.2.7]
If a manager receives an inform request from another manager, I wonder how it assigns the data to the proper agent.
When the inform request is received from an agent - like a trap - the IP address can be used to assign the data to the agent.
This case also seems to make more sense to me. Are there any real world applications where an inform is sent by a manager?
You can not change the IP address in INFORM PDU. This type of SNMP PDU does not have such field. So the receiver always uses src_ip of UDP datagram. The Agent Address is part of TrapV1 PDU only.

SNMP Server Connection

I am sending a SNMP trap to the SNMP server. But I have to print the log if the connection to the server is not established.
UdpAddress targetAddress = new UdpAddress("127.0.0.1/1985");
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString("public"));
target.setAddress(targetAddress);
target.setRetries(2);
target.setTimeout(1000);
target.setVersion(SnmpConstants.version1);
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
snmp.listen();
// prepare the PDU for sending
PDU command = new PDU();
command.setType(PDU.GET);
command.add(new VariableBinding(new
OID("1.3.6.1.4.1.1331.11.5.1.0")));
// now send the PDU
**// I HAVE TO CHECK WETHER CONNECTION IS ESTABLISHED OR NOT WITH SNMP SERVER. AS OF
NOW EVEN IF I DO NOT START SNMP SERVER THAN I AM NOT GETTING ANY EXCEPTION and IF I START
SNMP SERVER THEN MESSAGE HAS BEEN SENT TO SNMP SERVER.....MAY BE IN SEND METHOD..ITS
CONNECTS WITH SNMP SERVER....BUT I TRIED TO FIND OUT BUT COULDNT ABLE TO DO IT.....**
ResponseEvent responseEvent = snmp.send(pdu, target);
UDP is connectionless, so you have no way to know if the packet is received in this case.
as you been told UDP is connectionless, so you have no way to know if the packet is received in this case.
but if you really must to know that the SNMP manager is alive before you send the trap. you can create your own a handshake.
the logic is pretty simple and it goes something like that:
1) create in the MIB new leaf to indicates if the manager is connected and initial it to false.
2) send a trap to the manager.
2.1) if the manager is alive (receive the trap)
2.1.1) the manager send a set-request to the leaf with true.
the agent can read the value from it's on MIB and know if the manager is listening to traps
you can expend and improve the logic but the basic idea is clear I think
Although you want to send SNMP trap/notification in code you are doing the following
PDU command = new PDU();
command.setType(PDU.GET);
The above will result in sending an SNMP get request which should ideally fetch you a response however the port number (source or your client's source address) is where you should be listening. The above code snippet has some basic flaws as a result you are not getting desired results.
Some links that you may want to read up on SNMP4j to send notifications
https://www.jayway.com/2010/05/21/introduction-to-snmp4j/
http://lists.agentpp.org/pipermail/snmp4j/2006-April/001219.html

Receiving datagrams using Udp connection

In order to receive datagrams through an UDP connection I have created an object of type UDPClient.
receivedNotificationSock = new UdpClient();
However once done and on using the receive method:
receivedHostNameBuffer=receivedNotificationSock.Receive(ref receivedNotificationIP);
I am getting an exception saying that I must call the bind method.
But there is no bind method in the UDPClient class.
Could You guys please provide me with the code if possible as to what should be done to overcome this exception.
You need I think to know some more about sockets.
All sockets possess a port number. First, you create a socket - which is almost useless on its own. It just floats there. But then you bind it - you assign it a port number. Now it's useful - now you can send and receive data on it.
Remember, all UDP communications are defined by the quad data set of the IP and port of the source and the IP and port of the destination. A freshly created socket doesn't have an IP address or port; binding gives it an IP address and port.
Unfortunately, I'm not a C# programmer, so I can't properly answer your question. But at least you know why it's important.
Pass the port number into the constructor of your UDP client.
receivedNotificationSock = new UdpClient(21000);
You may need to change firewall settings to allow the bind, though a popup window normally opens when you first run this on your dev machine.
For Socket proramming you need to know the sequence of syscalls you need to do on client side and on the server side.
If you are writting a client :
you open a socket with a socket call.
you then connect to the server port with a connect call
once connect is successful
then you send the request to the server using either a send or sendto or a write
which results in reception of data that you can read using a receive or read
On Server Side
you create a socket
bind it to a port
start listening on the socket for incoming connections from various clients using a listen.
There is a non blocking way of listening for connections as well with a select syscall.
Once the you establish a connection you can essentially read the request and start processing it.
Here's an example in C# that may be useful to you.
http://www.developerfusion.com/article/3918/socket-programming-in-c-part-1/

Resources