SNMP4J包 TCP 訊息傳送時的乙個BUG

2021-06-27 00:13:46 字數 1375 閱讀 8650

在實際使用中,發現這樣的乙個問題,客戶端(工業級交換機)和本地服務端的連線總是中斷,當然不是超時自動清理的。

這個中斷,有時可以建立上並能正常使用,有時連線上了卻不正常使用這個連線。後台日誌列印,明明連線已經存在卻一直報錯說是通道已經關閉。

經過多次測試和斷點跟蹤,發現交換機在一定時間不實用的話就認定連線中斷,馬上進行連線重建,而此時如果服務端正在給客戶端傳送訊息,就會在一定機率上造成連線建立卻無法繼續使用的情況。

private void processpending() 

if (entry != null)

if ((s == null) || (s.isclosed()) || (!s.isconnected()))

pending.remove(entry);

socketchannel sc = null;

try

selector.wakeup();

logger.debug("trying to connect to "+address);

} catch (ioexception iox)

} else

selector.wakeup();

}}

跟蹤斷點會發現,如果客戶端不可用的情況下你傳送訊息,他會進if ((s == null) || (s.isclosed()) || (!s.isconnected())) 的判斷區域,那麼這個區域的**執行的操作卻是建立針對這個位址建立乙個客戶端連線然後傳送資料。

這顯然不對,而且因為他建立連線時正好處於交換機的重啟或連線重建時,不會報錯,所以就會造成這個訊息被當成自己是客戶端對方是服務端給處理了。

而執行 processpending 方法時,正好在 entry.getsocket().getchannel().close(); 之前交換機的客戶端連線過來了,連線剛剛建立這裡就執行了entry.getsocket().getchannel().close();  你再使用這個連線傳送訊息,就會一直提示通道已經關閉!

我的建議是,這裡不應該認定沒有連線存在就把這個訊息當客戶端訊息給傳送,應該是如果不是服務端再進行上面說的判斷區域。

private boolean serverenabled = false;
如果你是服務端,那麼這個屬性就是 true 。

所以訊息傳送時應該是這樣判斷:

// todo 如果本地不是服務端,則建立連線再傳送

if (!serverenabled) {

如果你的訊息都是當成服務端去傳送了,那麼這個連線一旦建立成功,且此時程式還在處理中,那麼訊息照樣是傳送成功的!

請您到iteye**看原創,謝謝!

! 

使用snmp4j實現Snmp功能(一)

上面的這段 直接參考snmp4j api說明文件中提供的例子,是乙個最簡單的snmp4j的應用。只要你的機器裡安裝了snmp通訊元件,上面的 應該可以執行成功。在上乙個例子中,我們只做了讀取的工作,接下來,我們進行一下設定操作,通過snmp修改讀取的機器名。public的預設許可權是唯讀,要想進行寫...

使用snmp4j實現Snmp功能(三)

前兩篇文章講了如何使用snmp4j實現set get 使用snmp4j實現snmp功能 一 以及傳送 接收trap 使用snmp4j實現snmp功能 二 功能。在我們前面的實現中,如果訪問mib庫中不存在的oid,get方式的話,我們會得到乙個null值,而set方式時agent端會把我們發過去的p...

利用snmp4j通過SNMP獲取遠端伺服器狀態

執行命令yum install net snmp utils net snmp 即可安裝。配置 vi etc snmp snmpd.conf 配置檔案,找到view systemview included這一行,在下面加上一行 view all included 1,同時修改一行 access no...