Java NIO無法綁定指定IP和端口解決方案
在使用SNMP4J時(shí),我想指定創(chuàng)建的客戶端使用的本地IP和端口,因?yàn)樵赟ocket時(shí)這是可以的,但是發(fā)現(xiàn)無法實(shí)現(xiàn)
因?yàn)镾NMP4J底層的通信是使用NIO實(shí)現(xiàn)的,而NIO編程時(shí)貌似就不能顯示的指定
例如在SNMP4J的DefaultTcpTransportMapping類里面,當(dāng)作為客戶端需要發(fā)送消息時(shí),程序首先判斷是否創(chuàng)建了這個(gè)客戶端,如果沒有在創(chuàng)建時(shí)看到這樣的代碼:
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.
*
* <p> The returned object will not declare any public methods that are not
* declared in the {@link java.net.Socket} class. </p>
*
* @return A socket associated with this channel
*/
public abstract Socket socket();
所以我直接判定Java NIO中,客戶端是無法指定自己的IP和端口的!
那么有人在想為什么需要指定自己的IP和端口?具體需求我就不再說了,在計(jì)算機(jī)上雖然只有一塊網(wǎng)卡,但是我們可以使用兼容的IP:

由于我的服務(wù)端程序以客戶端IP來判斷信息來源,現(xiàn)在我需要在我的電腦上做測(cè)試程序,需要同時(shí)邦定兩個(gè)IP地址進(jìn)行消息發(fā)送。
此時(shí)我就可以在高級(jí)設(shè)置里面設(shè)置兼容IP就可以,但是現(xiàn)在程序卻無法選擇。
在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 {
// 創(chuàng)建非邦定式連接對(duì)象
ServerSocket ss = new ServerSocket();
// 需要邦定的本地IP和地址
SocketAddress address = new InetSocketAddress("192.168.0.109", 2330);
// 將連接對(duì)象邦定到地址
ss.bind(address);
System.out.println("服務(wù)已經(jīng)啟動(dòng)");
while (true) {
// 接收請(qǐng)求
Socket socketClient = ss.accept();
// 客戶端IP
String ip = socketClient.getInetAddress().getHostAddress();
// 客戶端端口
int port = socketClient.getPort();
System.out.println("服務(wù)端收到請(qǐng)求:" + ip + "/" + port);
}
}
}
服務(wù)端很簡(jiǎn)單,你可以一行代碼搞定,也可以顯示的指定IP、端口,然后進(jìn)行顯示的服務(wù)連接操作:
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);
// 連接的遠(yuǎn)程服務(wù)地址
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);
}
}
注釋掉的內(nèi)容是一行搞定連接的方式。
經(jīng)過測(cè)試,如果想要修改所邦定的IP和顯示再次進(jìn)行連接操作,需要把設(shè)置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;
}
否則會(huì)報(bào)錯(cuò):
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)
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java并發(fā)編程包中atomic的實(shí)現(xiàn)原理示例詳解
這篇文章主要給大家介紹了關(guān)于Java并發(fā)編程包中atomic的實(shí)現(xiàn)原理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-09-09
Java利用套接字實(shí)現(xiàn)應(yīng)用程序?qū)?shù)據(jù)庫的訪問
所謂套接字(Socket),就是對(duì)網(wǎng)絡(luò)中不同主機(jī)上的應(yīng)用進(jìn)程之間進(jìn)行雙向通信的端點(diǎn)的抽象。這篇文章主要介紹了Java利用套接字實(shí)現(xiàn)應(yīng)用程序?qū)?shù)據(jù)庫的訪問,感興趣的可以了解一下2022-09-09
深入解析Java類加載的案例與實(shí)戰(zhàn)教程
本篇文章主要介紹Tomcat類加載器架構(gòu),以及基于類加載和字節(jié)碼相關(guān)知識(shí),去分析動(dòng)態(tài)代理的原理,對(duì)Java類加載相關(guān)知識(shí)感興趣的朋友一起看看吧2022-05-05
簡(jiǎn)述springboot及springboot cloud環(huán)境搭建
這篇文章主要介紹了簡(jiǎn)述springboot及springboot cloud環(huán)境搭建的方法,包括spring boot 基礎(chǔ)應(yīng)用環(huán)境搭建,需要的朋友可以參考下2017-07-07
SpringBoot項(xiàng)目中自定義Banner的技術(shù)指南
在 Spring Boot 項(xiàng)目中,當(dāng)應(yīng)用啟動(dòng)時(shí)會(huì)顯示默認(rèn)的 Spring 標(biāo)志和版本信息,定制化的啟動(dòng) Banner 不僅可以美化應(yīng)用,甚至可以提供一些關(guān)鍵信息,本文將介紹如何在 Spring Boot 項(xiàng)目中自定義啟動(dòng) Banner,需要的朋友可以參考下2025-03-03

