java端口映射_第1頁
java端口映射_第2頁
java端口映射_第3頁
java端口映射_第4頁
java端口映射_第5頁
已閱讀5頁,還剩23頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、下載源代碼  1.介紹:     本文手把手的詳解了jPortMap端口映射程序開發中的每一步,做為己運行在實際的企業項目中的應用, jPortMap程序較全面的展示了Thread、List、Vector、Socket、ServerSocket、Input/OutpuStream、File Read/Write、Properties等核心API的用法,是初學者快速進階的一個優秀案例。       在涉及內外網數據交換的網絡應用系統開發中,我們經常需要做端口映射,比如

2、放在外部網絡主機上的程序要與內部網絡上的某臺機器建主TCP/IP連結,如下圖(1)示:    C機器可以與A機連通,但要與B機連通,由與不在同一網絡,就無能為力了;這時,就需在A機器上做交換或是轉發,來接通C與B之間的TCP/IP連結,即C機先與A機器建立Socket連結,A再與B機建立連結,然后由A在中間轉發C與B通信的數據;B機器上可能運行著數據庫,WebService等在Tcp/IP上通信的程序,而C機器必須訪問這些服務。這里A機器就充當像現實生活中介紹人的角色,負責將C、B之間的通信數據流在Socket上轉發;圖1   

3、60; 因此,A機需實現端口轉發功能,在Liunx上,可以通過配置IPTable由OS實現,在本例中,我們將開發一個java實現的端口轉發程序jPortMap,此程序將運行在A機器上,以實現轉發C與B之間通信的轉發。2.源碼下載及測試說明:從www.NetJ上下載源代碼解壓后,可看到如下目錄結構:    現在,你可以修改一下jPortMap.cfg中的配置,比如,想通過本機的地址上的8899端口轉發到56,則這樣配置:#本地IPLocalIP.1 = #本地端口LocalPort.1 = 8

4、899#目標IPDestHost.1 = 56 #目標端口DestPort.1 = 80#客戶端IP過濾表,*表示許可模糊匹配AllowClient.1 = *.*.*.*,雙擊jPortMap.bat啟動程序后,在你的IE里輸入:8899試試看:)3.jPortMap程序類的構成說明:jPortMap由Main.java、Server.java、Transfer.java、Route.java、SysLog.java五個類構成。類文件功能概要:Main.java:程序啟動主類,負責從配置文件讀取轉發的配置參數,啟動轉發服務器;Server.ja

5、va:其實是一個ServerSocket服務器,接受C機器進入的Socket連結請求,生成Transfer.對象,由Transfer負責在本機(A上)轉發B和C之間的通信。Route.java:轉發對象的數據模板類,用來將轉發配置映射為java對象,以由Server,ransfer對象使用。Transfer.java:按字面意思,可理解為“傳送者”,如在圖示中,當C要通過A連結B時,是先連結到A機上,這里在C和A間生成一個socket對象,Transfer對象則使用這個生成的socket對象和這個傳輸任務的Route對象執行具體的轉發任務。SysLog.java:jPortMap是一個服務器端

6、程序,在運行中可能會出現錯誤,因此需要一個日志工具,日志工具在jPortMap中只有一個對象存在,負責記錄每天程序運行的信息,如錯誤,警行,一般信息等。配置文件:   cfgjPortMap.cfg:這是一個文本文件,其中存放jPortMap的配置數據,當程序啟動時,主類會從中讀取數據配置程序,以生成多個Route對象在內存中保持數據。4.Route.java解析:我們己經說明,Route類是轉發對象配置數據的模板類,當jPortMap啟運時,它需要知道如下配置:1. 有多少處轉發任務(意味著要監聽哪幾個ServerSocket);2. jPortMap程序對每個

7、轉發任務要啟動的監聽ServerSocket端口及所綁定的IP地址;3. 每個轉發任務的目標IP地址和端口;   因此,jPortMap一但啟動,可能會創建多個Route對象,而每個具體的Route對象則保布著一個轉發任務的以上配置數據。另外,從安全方面著想,我們的jPortMap程序還需要對請求進入的連結進行安全管理,這里我們簡單的用IP過濾的方法,即jPortMap中ServerSocekt監聽到的進入連結請求會認證IP地址,如發現IP地址沒有在許可的列表中,則斷開這個請求;所以Route類還要保存每個任務對應的許可IP表;我們的Route.java源文件如下

8、: /* * Route.java * * Created on 2006年12月28日, 下午12:36 * * To change this template, choose Tools | Template Manager * and open the template in the editor. */package java.jportmap;/* *轉發任務的配置數據對象模板 * * author javafound */public class Route public Route() /jPortMap綁定的IP String LocalIP="" /監聽的

9、端口 int LocalPort=0; /轉發數據的目標機器IP String DestHost="" /轉發的目標端口 int DestPort=0; /這個轉發上許可進入的IP列表 String AllowClient="" /重寫的toString方法,輸出具體Route對象的信息以便debug public String toString() StringBuffer stb = new StringBuffer(); stb.append(" LocalADD " + LocalIP); stb.append("

10、:" + LocalPort); stb.append(" ->DestHost " + DestHost); stb.append(" :" + DestPort); stb.append(" (AllowClient) " + AllowClient); return stb.toString();      可以比對cfgjPortMap.cfg(可用notepad打開)中的內容,Route類只需要據文本件中的配配生成多個Route對象或者說轉發任務,再由其它對象

11、來使用,因此,Route類的功能和結構很簡單,就像映射表結構的javaBean一樣,只是負責保存數據在內存中。5. SysLog.java解析:SysLog保存每天的日志信息到指定的目錄下,簡單的說就是提供方法供別的對象來調用,寫內容到文件中:package java.jportmap;import java.io.*;import java.util.Calendar;/* * Title: 端口轉發器 * Description:日志工具類 * Copyright: Copyright (c) 2005 * author javafound * version 1.0 */public c

12、lass SysLog /記錄輸出一般信息 public static void info(String s) writeToTodayLog("INFO :", s); /記錄警告信息 public static void warning(String s) writeToTodayLog("WARN:", s); /記錄錯誤信息public static void severe(String s) writeToTodayLog("ERROR:", s); /輸出到當天日志文件的具體實現 private static void w

13、riteToTodayLog(String flag, String msg) RandomAccessFile raf = null; try Calendar now = Calendar.getInstance(); String yyyy = String.valueOf(now.get(java.util.Calendar.YEAR); String mm = String.valueOf(now.get(Calendar.MONTH) + 1); String dd = String.valueOf(now.get(Calendar.DAY_OF_MONTH); String hh

14、 = String.valueOf(now.get(Calendar.HOUR_OF_DAY); String ff = String.valueOf(now.get(Calendar.MINUTE); String ss = String.valueOf(now.get(Calendar.SECOND); mm = (1 = mm.length() ? ("0" + mm) : mm; dd = (1 = dd.length() ? ("0" + dd) : dd; hh = (1 = hh.length() ? ("0" + hh

15、) : hh; ff = (1 = ff.length() ? ("0" + ff) : ff; ss = (1 = ss.length() ? ("0" + ss) : ss; String yyyymmdd = yyyy + mm + dd; String hhffss=hh+ff+ss; String path = System.getProperties().getProperty("user.dir") + File.separator + "log" File p = new File(path); i

16、f (!p.exists() p.mkdirs(); path += File.separator + "jPortMap_" + yyyymmdd + ".log" File f = new File(path); if (f.isDirectory() f.delete(); raf = new RandomAccessFile(f, "rw"); raf.seek(raf.length(); raf.writeBytes(hhffss+" "+flag + " : " + msg + &q

17、uot;rn"); raf.close(); catch (Exception ex) System.out.println("write file has error=" + ex); /* Creates a new instance of SysLog *做為一個工具類,一般不需要實例化,所以此處private */ private SysLog() 說明:首先我們看到提供的三個公用靜態方法:/記錄一般信息public static void info(String s) /記錄警告信息public static void warning(String s)

18、/記錄錯誤信息public static void severe(String s)      SysLog做為系統中的工具類,一般是不需要實例化的,所以只提供調用功能即可,這三個調用方法為其它對象提供了調用接口,分別輸出不同類型的信息到目志中,而調用對象并不需要去關心具體日志的格式,日志文件命令,文件讀寫等問題-只需傳入要記錄的消息即可。    System.getProperties()返回一個Properties對象,其實是一個Map接口的實現,其中存入格式為 名字:值 一一對應的表,系統的許多環境變量,如程

19、序運行的當前目錄user.dir,操作系統類型,java當前版本等都在其中存放。    RandomAccessFile:在寫日志時使用了這個類向日志文件中寫入內容,其中seek(int length)可以指定跳過文件中內容的長度后再開始寫入;這樣我們的日志就不會丟失。6.Server.java解析:     如其名,Server是一個轉發服務器的實現類,我們的jPortMap可同時執行多個轉發服務,所以每個Server對象都將做為一個獨立的線程運行,在jPortMap.cfg中配置了幾個轉發任務,系統就

20、會實例幾個Route對象,并生成對應個數的的Server對象,每個Server對象使用自己的一個Route對象的數據在指定的端口啟動監聽服務,等待客戶端(如前面圖示則是C機器)發起的連結,接收到連結請求并通過IP驗證后,這個Server對象則將具體的轉發任務交給自己的一個Transfer對象去獨立處理,而Server對象則繼續運行,等待到來的連結請求。     我們可以將這個Server理解為一個看門人的角色-使用ServerSocket監聽指定端口,等待到來的連結,它只負責接待來客,并核查來客的身份,如核查通過,至于來客進的門怎么辦,它不管-

21、由它所持有的另外一個對象Transfer類的一個實例去處理。解析代碼如下:package java.jportmap;import .*;import java.util.*;/* * Title: 端口轉發器 * Description:啟動監聽服務 * Copyright: Copyright (c) 2005 * author javafound * version 1.0 */public class Server extends Thread /創建一個轉發服務器 public Server(Route route, int id) this.route = route; conne

22、ctionQueue = new Vector(); myID = id; start(); /關閉這個服務器: public void closeServer() isStop = true; if (null != myServer) closeServerSocket(); while (this.connectionQueue.size() > 0) Transfer tc = (Transfer) connectionQueue.remove(0); tc.closeSocket(tc.socket); tc = null; /啟動轉發服務器的執行線程 public void

23、run() SysL(" start Transfer.:" + route.toString(); ServerSocket myServer = null; try InetAddress myAD = Inet4Address.getByName(route.LocalIP); myServer = new ServerSocket(route.LocalPort, 4, myAD); catch (Exception ef) SysLog.severe("Create Server " + route.toString() + &q

24、uot; error:" + ef); closeServerSocket(); return; SysL("Transfer Server : " + route.toString() + " created OK"); while (!isStop) String clientIP = "" try Socket sock = myServer.accept(); clientIP = sock.getInetAddress().getHostAddress(); if (checkIP(route, cl

25、ientIP) SysLog.warning(" ransfer Server : " + route.toString() + " Incoming:" + sock.getInetAddress(); sock.setSoTimeout(0); connCounter+; Transfer myt = new Transfer(sock, route); connectionQueue.add(myt); else SysLog.warning(" ransfer Server : " + route.toString() + &

26、quot; Refuse :" + sock.getInetAddress(); closeSocket(sock); catch (Exception ef) SysLog.severe(" Transfer Server : " + route.toString() + " accept error" + ef); /檢測進入的IP是否己許可 private static boolean checkIP(Route route, String inIP) String inI = string2StringArray(inIP, "

27、;."); String list = string2StringArray(route.AllowClient, "."); if (inI.length != list.length) SysLog.severe(" Transfer Server Error Cfg AllowClient : " + route.toString(); return false; for (int i = 0; i < inI.length; i+) if (!inIi.equals(listi) && !(listi.equals

28、("*") System.out.println(": " + inIi + " :" + listi); return false; return true; /* * param srcString 原字符串 * param separator 分隔符 * return 目的數組 */ private static final String string2StringArray(String srcString, String separator) int index = 0; String temp; StringTokeniz

29、er st = new StringTokenizer(srcString, separator); temp = new Stringst.countTokens(); while (st.hasMoreTokens() tempindex = st.nextToken().trim(); index+; return temp; /關閉ServerSocket private void closeServerSocket() try this.myServer.close(); catch (Exception ef) private void closeSocket(Socket s)

30、try s.close(); catch (Exception ef) /服務器 private ServerSocket myServer = null; /連結隊列控制 private boolean isStop = false; / private Vector connectionQueue = null; private int connCounter = 0; / 路由對象 private Route route = null; /連結的ID號,暫未用 private static int myID = 0;  Server類關鍵功能是在一個獨立的線程中執行監

31、聽任務,當我們實例化一個ServerSocket時,即綁定了本機的一個IP和端口,這個ServerSocket對象就在這個地址(由IP和端口組成)上通過調用accept()方法等待客戶端連結,默認情況下,這個等待會一直持續,直到有一個連結進入-生成一個socket對象;而我們的ServerSocket.accept()是在一個wilhe循環中,這保證了監聽服務器不會中途退出。7. Transfer.java解析     在分析Server.java中我們看到,Server做為一個服務器,在與客戶端建立連結后使用生成的Socket對象和自己的Ro

32、utc對象來實例化一個Transfer,具體的傳輸工作就交給了Transfer對象完成。   Server生成的Socket對象是機器C與A之間連結的一個代碼,通過這個Socekt對象上的Input/OutPut Stream,可以讓C與A之間通信-工作還只完成了一半,這里我們還需要建立A與B之間的Socket連結,這里就出現了兩個Socket連結,分別是C與A間,我們叫SocketCA;A與B間我們假設叫做SocketAB; Transfer對象的任務就是行建立SocketAB,然后,將SocketCA的輸入寫入到SocketAB的輸出流,將SocketAB的輸

33、出流寫到SocketCA的輸出流中,這樣,就完成了C,B機器之間的數據轉發。package java.jportmap;import .*;import java.io.*;/* * Title: 端口轉發器 * Description: 對連結進行轉發處理 * Copyright: Copyright (c) 2005 * author javafound * version 1.0 */public class Transfer extends Thread /* * 創建傳輸對象 * param s Socket :進入的socket * param route Route:轉發配置 *

34、/ public Transfer(Socket s, Route route) this.route = route; this.socket = s; this.start(); / 執行操作的線程 public void run() Socket outbound = null; try outbound = new Socket(route.DestHost, route.DestPort); socket.setSoTimeout(TIMEOUT); InputStream is = socket.getInputStream(); outbound.setSoTimeout(TIM

35、EOUT); OutputStream os = outbound.getOutputStream(); pipe(is, outbound.getInputStream(), os, socket.getOutputStream(); catch (Exception e) SysLog.severe(" transfer error:" +route.toString()+ " :" + e); finally SysLog.warning("Disconnect :"+ route.toString(); closeSocket

36、(outbound); closeSocket(socket); /* *傳輸的實現方法 */ private void pipe(InputStream is0, InputStream is1, OutputStream os0, OutputStream os1) try int ir; byte bytes = new byteBUFSIZ; while (true) try if (ir = is0.read(bytes) > 0) os0.write(bytes, 0, ir); else if (ir < 0) break; catch (InterruptedIOE

37、xception e) try if (ir = is1.read(bytes) > 0) os1.write(bytes, 0, ir); / if (logging) writeLog(bytes,0,ir,false); else if (ir < 0) break; catch (InterruptedIOException e) catch (Exception e0) SysLog.warning(" Method pipe" + this.route.toString() + " error:" + e0); /關閉socket

38、 void closeSocket(Socket s) try s.close(); catch (Exception ef) /傳輸任務的Route對象Route route = null; / 傳入數據用的SocketSocket socket; /超時 static private int TIMEOUT = 1000; /緩存 static private int BUFSIZ = 1024;8.Main.java解析OK,至此己萬事具備!我們需要一個啟動主類,根據讀入的配置文件數據來啟動轉發服務器,執行轉發工作:package java.jportmap;import java.io

39、.*;import java.util.*;import .*;/* * Title: 端口轉發器 * Description:啟動主類:讀取配置,啟動監聽服務 * Copyright: Copyright (c) 2005 * author javafound * version 1.0 */public class Main /start. public static void main(String args) startService(); /start public static void startService() if (!loadCfgFile() System.exit(1

40、); while (serverList.size() > 0) Server ts = serverList.remove(0); ts.closeServer(); for (int i = 0; i < routeList.size(); i+) Route r = routeList.get(i); Server server = new Server(r, i); serverList.add(server); / 停止服務接口,備用其它模塊調用 public static void stop() while (serverList.size() > 0) Serv

41、er ts = serverList.remove(0); ts.closeServer(); /* *從配置文件讀取數據,生成Route對象 * read cfg parameter * return boolean */ private static boolean loadCfgFile() try String userHome = System.getProperties().getProperty("user.dir"); if (userHome = null) userHome = "" else userHome = userHome

42、+ File.separator; userHome += "cfg" + File.separator + "jPortMap.cfg" InputStream is = new FileInputStream(userHome); Properties pt = new Properties(); pt.load(is); /共有幾個業務模塊 int ServiceCount = Integer.parseInt(pt.getProperty("TransferCount"); for (; ServiceCount > 0

43、; ServiceCount-) Route r = new Route(); r.LocalIP = pt.getProperty("LocalIP." + ServiceCount).trim(); r.LocalPort = Integer.parseInt(pt.getProperty("LocalPort." + ServiceCount).trim(); r.DestHost = pt.getProperty("DestHost." + ServiceCount).trim(); r.DestPort = Integer.

44、parseInt(pt.getProperty("DestPort." + ServiceCount).trim(); r.AllowClient = pt.getProperty("AllowClient." + ServiceCount). trim(); routeList.add(r); is.close(); SysL("ystem Read cfg file OK"); catch (Exception e) System.out.println("找不到配置文件:"+e); SysLog

45、.severe("loadCfgFile false :" + e); return false; return true; /Server服務器集合 private static List< Server> serverList = new ArrayList(); /Route集合 private static List< Route> routeList = new ArrayList();     Main類中需要注意的是loadCfgFile()方法,它用來讀取當前目錄下面cfg/jPortMap.c

46、fg文件中的配置數據,如讀取成功,返加ture值,如讀取失敗,程序測會退出。另外:/Server服務器集合private static List<Server> serverList = new ArrayList();/Route集合private static List<Route> routeList = new ArrayList();這兩行代碼,生成兩個列表,來保存己啟動的Server對象和Route對象。    現在,我們只要啟動Main類,jPortMap就開始運行了,同時會在log目錄下行成每天的運行日志;當然,千

47、萬不要忘了cfg/目錄下面jPortMap.cfg中配置轉發的參數,配置的具體說明在該文件中有注解。源碼目錄結構圖(NetBean中):9.改進設想:      無論如何,這還是個比較簡陋的程序!假如我們把配置改成XML格式、假如我們使用Thread Pool來執行任務、假如我們使用NIO、假如我們再做一套PL的UI界面.,您的任何建議,都會是對jPortMap走向完美的支持,請登陸www.NetJ發表您的看法,發布您的創新!當然,www.NetJ現在己增加了許多新東東讓您欣賞!下載源代碼  1.介紹:  

48、;   本文手把手的詳解了jPortMap端口映射程序開發中的每一步,做為己運行在實際的企業項目中的應用, jPortMap程序較全面的展示了Thread、List、Vector、Socket、ServerSocket、Input/OutpuStream、File Read/Write、Properties等核心API的用法,是初學者快速進階的一個優秀案例。       在涉及內外網數據交換的網絡應用系統開發中,我們經常需要做端口映射,比如放在外部網絡主機上的程序要與內部網絡上的某臺機器建主TC

49、P/IP連結,如下圖(1)示:    C機器可以與A機連通,但要與B機連通,由與不在同一網絡,就無能為力了;這時,就需在A機器上做交換或是轉發,來接通C與B之間的TCP/IP連結,即C機先與A機器建立Socket連結,A再與B機建立連結,然后由A在中間轉發C與B通信的數據;B機器上可能運行著數據庫,WebService等在Tcp/IP上通信的程序,而C機器必須訪問這些服務。這里A機器就充當像現實生活中介紹人的角色,負責將C、B之間的通信數據流在Socket上轉發;圖1     因此,A機需實現端口轉發功能,在Liunx上,可以通過配置IPTable由OS實現,在本例中,我們將開發一個java實現的端口轉發程序jPortMap,此程序將運行在A機器上,以實現轉發C與B之間通信的轉發。2.源碼下載及測試說明:從www.NetJ上下載源代碼解壓后,可看到如下目錄結構:    現在,你可以修改一下jPortMap.cfg中的配置,比如,想通過本機的地址上的8899端口轉發到56,則這樣配置:#本地I

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論