Java 集成Ftp Server踩到的坑
FTP 協(xié)議簡單介紹
FTP 本身是基于TCP的,那么肯定會有IP和端口對不對?
回答:是對的
一般默認的Ftp Server默認端口21,這里我單純的以為他只會用到端口21(怪我之前沒有好好掃盲)。
**踩到的第一個坑 "防火墻" **
當我的FTP server集成完后,防火墻只開放了我監(jiān)聽的7000端口。興高采列的上測試服務(wù)器測試了。
然后在測試服務(wù)器用ftp 命令連接了一下,嗯,非常順利竟然連接成功,然后防火墻開了7000端口。過了一會發(fā)現(xiàn)用別的機器連接好像不行了。這出現(xiàn)了大寫的尷尬。經(jīng)過反復測試發(fā)現(xiàn)關(guān)掉防火墻就好了,在這里我還不知道FTP 有個控制端口和連接端口。
簡單的說控制端口用來登錄的,連接端口是在登錄之后使用的,至于使用什么端口要看主動模式和被動模式了。
Mina ftpserver 使用
這個用起來也很簡單的
FtpServerFactory serverFactory = new FtpServerFactory();
ListenerFactory factory = new ListenerFactory();
// set the port of the listener
//↓ 就是這這里我一直以為是只會用這一個端口,導到我踩了第一個坑
//原來這個只是控制端口,還有個連接端口,默認是使用的20(主動模式),被動模式下使用隨機的端口。
factory.setPort(2221);
// replace the default listener
serverFactory.addListener("default", factory.createListener());
// start the server
FtpServer server = serverFactory.createServer();
server.start();
接著說,話說防火墻也被我關(guān)了。這下應該沒啥事兒,嗯~話說這種情況在局域網(wǎng)(客戶端和服務(wù)器),真的一點問題都沒有。
** 當我們的客戶端程序搬到外網(wǎng)之后,F(xiàn)TP server在內(nèi)網(wǎng)通過路由器的端口映射 **
可能有小伙伴看不大明白,弄張圖吧:
左邊就是我的服務(wù)器,這樣部署后,發(fā)現(xiàn)客戶端死活連不上服務(wù)器,但是可以登錄,嘗試過主動模式、被動模式、將所有端口映射還是不起作用。
找文檔,找資料。找到了一個可以設(shè)備被動模式和主動模式使用的端口如下:
DataConnectionConfigurationFactory dccFactory = new DataConnectionConfigurationFactory();
dccFactory.setActiveLocalPort("7001"); //主動模式使用的端口
dccFactory.setPassiveIpCheck(true);
dccFactory.setPassivePorts("7001-7002"); //被動模式使用的端口范圍
DataConnectionConfiguration dcc=dccFactory.createDataConnectionConfiguration();
factory.setDataConnectionConfiguration(dcc);
到這里算是有一點收獲,總算把使用的端口搞明白了。但是還是沒解決客戶端不能連的問題。
接著找,再仔細的看主動模式和被動模式
主動模式、被動模式
這二個模式都是針對服務(wù)器而言
主動模式
當客戶端登錄服務(wù)器成功后,客戶端告訴服務(wù)器客戶端開放的端口,然后服務(wù)器主動去連接客戶端告訴過來的端口
被動模式
當客戶端登錄服務(wù)器成功后,服務(wù)器告訴客戶端我開放的端口,然后客戶端來連接服務(wù)器的端口,相當于是服務(wù)器一直是被動的等待連接
到這兒可能有點思路了,確定我的服務(wù)器一定是使用被動模式。通過日志發(fā)現(xiàn)被動模式使用的IP不對,
DataConnectionConfigurationFactory dccFactory = new DataConnectionConfigurationFactory();
dccFactory.setActiveLocalPort(activeLocalPort);
dccFactory.setPassiveIpCheck(true);
//↓ 就是這個,我的服務(wù)器內(nèi)網(wǎng)IP是192.168.1.10,路由器的ip是另一個。當我沒有設(shè)置這個選擇,當客戶端登錄成功后
//這里默認返回的是192.168.1.10的IP給客戶端,客戶端當然連接不成功了,因為客戶端根本不在我們一個局域網(wǎng)里面。
//所以這里我們一般要設(shè)置成外網(wǎng)ip(也可以設(shè)置域名,這樣不用擔心ip被變化的問題了)
dccFactory.setPassiveExternalAddress(passiveExternalAddress);
dccFactory.setPassivePorts(passivePorts);
DataConnectionConfiguration dcc=dccFactory.createDataConnectionConfiguration();
好了。到這里問題總算解決了~