在使用SNMP4J时,我想指定创建的客户端使用的本地IP和端口,因为在Socket时这是可以的,但是发现无法实现
因为SNMP4J底层的通信是使用NIO实现的,而NIO编程时貌似就不能显示的指定
例如在SNMP4J的DefaultTcpTransportMapping类里面,当作为客户端需要发送消息时,程序首先判断是否创建了这个客户端,如果没有在创建时看到这样的代码:
SocketChannel sc = null;
try {
sc = SocketChannel.open();
sc.configureBlocking(false);
sc.connect(new InetSocketAddress(((TcpAddress) address).getInetAddress(),((TcpAddress) address).getPort()));
s = sc.socket();
entry = new SocketEntry((TcpAddress) address, s);
entry.addMessage(message);
sockets.put(address, entry);
synchronized (pending) {
pending.add(entry);
}
selector.wakeup();
logger.debug("Trying to connect to " + address);
} catch (IOException iox) {
logger.error(iox);
throw iox;
}
即使在SocketChannel中,他的Socket变量定义也是不能修改的:
/**
* Retrieves a socket associated with this channel.
*
*
The returned object will not declare any public methods that are not
* declared in the {@link java.net.Socket} class.
*
* @return A socket associated with this channel
*/
public abstract Socket socket();
所以我直接判定Java NIO中,客户端是无法指定自己的IP和端口的!
那么有人在想为什么需要指定自己的IP和端口?具体需求我就不再说了,在计算机上虽然只有一块网卡,但是我们可以使用兼容的IP:
由于我的服务端程序以客户端IP来判断信息来源,现在我需要在我的电脑上做测试程序,需要同时邦定两个IP地址进行消息发送。
此时我就可以在高级设置里面设置兼容IP就可以,但是现在程序却无法选择。
在Socket里面可以这样写:
package com.xidian.nms.socket;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
public class SocketServer {
public static void main(String[] args) throws Exception {
// 创建非邦定式连接对象
ServerSocket ss = new ServerSocket();
// 需要邦定的本地IP和地址
SocketAddress address = new InetSocketAddress("192.168.0.109", 2330);
// 将连接对象邦定到地址
ss.bind(address);
System.out.println("服务已经启动");
while (true) {
// 接收请求
Socket socketClient = ss.accept();
// 客户端IP
String ip = socketClient.getInetAddress().getHostAddress();
// 客户端端口
int port = socketClient.getPort();
System.out.println("服务端收到请求:" + ip + "/" + port);
}
}
}
服务端很简单,你可以一行代码搞定,也可以显示的指定IP、端口,然后进行显示的服务连接操作:
package com.xidian.nms.socket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
public class SocketClient {
public static void main(String[] args) throws Exception{
Socket socket = new Socket();
// 需要邦定的本地IP
InetAddress iaddThis = InetAddress.getByName("192.168.1.109");
// 需要邦定的本地地址
SocketAddress saddThis = new InetSocketAddress(iaddThis,2331);
socket.bind(saddThis);
// 连接的远程服务地址
InetAddress iaddRe = InetAddress.getByName("192.168.0.109");
SocketAddress saddRe = new InetSocketAddress(iaddRe,2330);
// 显示连接
socket.connect(saddRe);
//Socket socket = new Socket("192.168.0.109", 2330);
}
}
注释掉的内容是一行搞定连接的方式。
经过测试,如果想要修改所邦定的IP和显示再次进行连接操作,需要把设置NIO同步的代码放到后面:
try {
sc = SocketChannel.open();
s = sc.socket();
s.bind(new InetSocketAddress("192.168.0.109", 999));
s.connect(new InetSocketAddress(((TcpAddress) address).getInetAddress(),((TcpAddress) address).getPort()));
sc.configureBlocking(false);
entry = new SocketEntry((TcpAddress) address, s);
entry.addMessage(message);
sockets.put(address, entry);
synchronized (pending) {
pending.add(entry);
}
selector.wakeup();
logger.debug("Trying to connect to " + address);
} catch (IOException iox) {
logger.error(iox);
throw iox;
}
否则会报错:
Exception in thread "main" java.nio.channels.IllegalBlockingModeException
at sun.nio.ch.SocketAdaptor.connect(SocketAdaptor.java:76)
at sun.nio.ch.SocketAdaptor.connect(SocketAdaptor.java:65)
at org.snmp4j.transport.DefaultTcpTransportMapping$ServerThread.sendMessage(DefaultTcpTransportMapping.java:503)
at org.snmp4j.transport.DefaultTcpTransportMapping.sendMessage(DefaultTcpTransportMapping.java:183)
at org.snmp4j.MessageDispatcherImpl.sendMessage(MessageDispatcherImpl.java:214)
at org.snmp4j.MessageDispatcherImpl.sendPdu(MessageDispatcherImpl.java:475)
at org.snmp4j.Snmp.sendMessage(Snmp.java:1110)
at org.snmp4j.Snmp.send(Snmp.java:914)
at org.snmp4j.Snmp.send(Snmp.java:894)
at org.snmp4j.Snmp.send(Snmp.java:859)
at com.xidian.nms.snmp.Snmp4jGet.sendPDU(Snmp4jGet.java:59)
at com.xidian.nms.snmp.Snmp4jGet.main(Snmp4jGet.java:38)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持云海天教程。
原文链接:https://www.iteye.com/blog/cuisuqiang-1821019