java nio 端口_Java NIO无法绑定指定IP和端口解决方案

在使用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:

c1ab7d9b7ace95683849290ffc37d716.png

由于我的服务端程序以客户端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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值