Java NIO無(wú)法綁定指定IP和端口解決方案
在使用SNMP4J時(shí),我想指定創(chuàng)建的客戶端使用的本地IP和端口,因?yàn)樵赟ocket時(shí)這是可以的,但是發(fā)現(xiàn)無(wú)法實(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中,客戶端是無(wú)法指定自己的IP和端口的!
那么有人在想為什么需要指定自己的IP和端口?具體需求我就不再說(shuō)了,在計(jì)算機(jī)上雖然只有一塊網(wǎng)卡,但是我們可以使用兼容的IP:
由于我的服務(wù)端程序以客戶端IP來(lái)判斷信息來(lái)源,現(xiàn)在我需要在我的電腦上做測(cè)試程序,需要同時(shí)邦定兩個(gè)IP地址進(jìn)行消息發(fā)送。
此時(shí)我就可以在高級(jí)設(shè)置里面設(shè)置兼容IP就可以,但是現(xiàn)在程序卻無(wú)法選擇。
在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)文章
Java8新特性之空指針異常的克星Optional類的實(shí)現(xiàn)
這篇文章主要介紹了Java8新特性之空指針異常的克星Optional類的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10淺談SpringCloud?Alibaba和SpringCloud的區(qū)別
這篇文章主要介紹了淺談SpringCloud?Alibaba和SpringCloud的區(qū)別,Spring?Cloud?Netflix框架也屬于Spring?Cloud,但是Netflix并不是由spring來(lái)進(jìn)行開發(fā)的,需要的朋友可以參考下2023-05-05在Spring AOP中代理對(duì)象創(chuàng)建的步驟詳解
今天和小伙伴們聊一聊 Spring AOP 中的代理對(duì)象是怎么創(chuàng)建出來(lái)的,透過這個(gè)過程再去熟悉一下 Bean 的創(chuàng)建過程,感興趣的小伙伴跟著小編一起來(lái)看看吧2023-08-08Java使用TCP實(shí)現(xiàn)數(shù)據(jù)傳輸實(shí)例詳解
這篇文章主要介紹了Java使用TCP實(shí)現(xiàn)數(shù)據(jù)傳輸實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-06-06淺談mybatisPlus的Ipage分頁(yè)和map參數(shù)的問題
這篇文章主要介紹了mybatisPlus的Ipage分頁(yè)和map參數(shù)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12springcloud整合gateway實(shí)現(xiàn)網(wǎng)關(guān)的示例代碼
本文主要介紹了springcloud整合gateway實(shí)現(xiàn)網(wǎng)關(guān)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01三道java新手入門面試題,通往自由的道路--鎖+Volatile
這篇文章主要為大家分享了最有價(jià)值的3道多線程面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,對(duì)hashCode方法的設(shè)計(jì)、垃圾收集的堆和代進(jìn)行剖析,感興趣的小伙伴們可以參考一下2021-07-07