Java NIO无法绑定指定IP和端口解决方案

网友投稿 529 2022-11-16


Java NIO无法绑定指定IP和端口解决方案

在使用SNMP4J时,我想指定创建的客户端使用的本地IP和端口,因为在Socket时这是可以的,但是发现无法实现

因为SNMP4J底层的通信IzFQm是使用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 http://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 {http://

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)


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SpringBoot使用Thymeleaf模板引擎访问静态html的过程
下一篇:详解java中DelayQueue的使用
相关文章

 发表评论

暂时没有评论,来抢沙发吧~