java語言

當前位置 /首頁/計算機/java語言/列表

java讀取使用者登入退出日誌上傳服務端

具體實現程式碼:

java讀取使用者登入退出日誌上傳服務端

  1.

package ; import eredReader;import ;import OutputStream;import ception;import tStreamReader;import utStreamWriter;import tWriter;import erSocket;import et;import Map;import ;import ;import kingQueue;import utorService;import utors;import edBlockingQueue; import ment;import ent;import eader; /** * DMS服務端,用來接收每個客戶端傳送過來的 * 配對日誌並儲存在本地檔案中 * @author Administrator * */public class DMSServer { //屬性定義 //用來接收客戶端連線的服務端的ServerSocket private ServerSocket server; //用來管理處理客戶端請求的執行緒的執行緒池 private ExecutorService threadPool; //儲存所有客戶端傳送過來配對日誌的檔案 private File serverLogFile; //訊息佇列 private BlockingQueuemessageQueue = new LinkedBlockingQueue(); public DMSServer() throws Exception{ try { tln("服務端正在初始化..."); //1 解析配置檔案 Mapconfig = loadConfig(); //2 根據配置檔案內容初始化屬性 init(config); tln("服務端初始化完畢..."); } catch (Exception e) { tln("初始化服務端失敗!"); throw e; } } /** * 構造方法初始化第一步,解析配置檔案 * @return 返回的Map中儲存的是配置檔案中的 * 每一條內容,其中key:標籤的名字, * value為標籤中間的文字 * @throws Exception */ private MaploadConfig() throws Exception{ try { SAXReader reader = new SAXReader(); Document doc = (new File("")); Element root = ootElement(); Mapconfig = new HashMap(); /* * 獲取標籤中的所有子標籤 * 並將每一個子標籤的名字作為key,中間的 * 文字作為value存入Map集合 */ Listlist = ents(); for(Element e : list){ String key = ame(); String value = extTrim(); (key, value); } return config; } catch (Exception e) { tln("解析配置檔案異常!"); tStackTrace(); throw e; } } /** * 構造方法初始化第二步,根據配置項初始化屬性 * @param config * @throws Exception */ private void init(Mapconfig) throws Exception{ /* * 用配置檔案中的初始化屬性:serverLogFile * 用配置檔案中的初始化屬性:threadPool,這裡建立固定大小執行緒池。該值作為執行緒池執行緒數量 * 用配置檔案中的初始化屬性:server,這裡這個值為ServerSocket的服務埠 */ er = new ServerSocket( eInt(("serverport")) ); erLogFile = new File( ("logrecfile") ); adPool = ixedThreadPool( eInt(("threadsum")) ); } /** * 服務端開始工作的方法 * @throws Exception */ public void start() throws Exception{ /* * 實現要求: * 首先單獨啟動一個執行緒,用來執行SaveLogHandler * 這個任務,目的是儲存所有配對日誌 * 然後開始迴圈監聽服務端埠,一旦一個客戶端連線了, * 就例項化一個ClientHander,然後將該任務交給執行緒池 * 使其分配執行緒來處理與該客戶端的互動。 * */ try { tln("服務端開始工作..."); SaveLogHandler slh=new SaveLogHandler(); new Thread(slh)t(); while(true){ Socket socket=pt(); ute(new ClientHandler(socket)); } } catch (Exception e) { tStackTrace(); throw e; } } public static void main(String[] args) { try { DMSServer server = new DMSServer(); t(); } catch (Exception e) { tln("啟動服務端失敗!"); } } /** * 該執行緒負責從訊息佇列中取出每一條配對日誌, * 並存入到serverLogFile檔案 * @author Administrator * */ private class SaveLogHandler implements Runnable{ public void run(){ PrintWriter pw = null; try { pw = new PrintWriter( new FileOutputStream( serverLogFile,true ) ); while(true){ if(()>0){ tln(()); }else{ h(); p(500); } } } catch (Exception e) { tStackTrace(); } finally{ if(pw != null){ e(); } } } } /** * 處理一個指定客戶端請求 * @author Administrator * */ private class ClientHandler implements Runnable{ private Socket socket; public ClientHandler(Socket socket){ et = socket; } public void run(){ /* * 思路: * 首先接收客戶端傳送過來的所有配對日誌, * 直到讀取到"OVER"為止,然後將這些配對 * 日誌儲存到本地的檔案中,並回復客戶端 * "OK" * 執行步驟: * 1:通過Socket建立輸出流,用來給客戶端 * 傳送響應 * 2:通過Socket建立輸入流,讀取客戶端傳送 * 過來的日誌 * 3:迴圈讀取客戶端傳送過來的每一行字串,並 * 先判斷是否為字串"OVER",若不是,則是 * 一條配對日誌,那麼儲存到本地檔案,若是, * 則停止讀取。 * 4:成功讀取所有日誌後回覆客戶端"OK" */ PrintWriter pw = null; try { //1 pw = new PrintWriter( new OutputStreamWriter( utputStream(),"UTF-8" ) ); //2 BufferedReader br = new BufferedReader( new InputStreamReader( nputStream(),"UTF-8" ) ); //3 String message = null; while((message = Line())!=null){ if("OVER"ls(message)){ break; } //將該日誌寫入檔案儲存 r(message); } //4 tln("OK"); h(); } catch (Exception e) { tStackTrace(); tln("ERROR"); h(); } finally{ try { //與客戶端斷開連線釋放資源 e(); } catch (IOException e) { tStackTrace(); } } } }}

  2.

package ; import eredReader;import ;import ception;import tStreamReader;import utStreamWriter;import tWriter;import omAccessFile;import et;import yList;import Map;import ;import ;import y;import ; import ment;import ent;import eader; import ata;import ec; /** * 該客戶端執行在給使用者提供unix服務的伺服器上。 * 用來讀取並收集該伺服器上使用者的上下線資訊,並 * 進行配對整理後傳送給服務端彙總。 * @author Administrator * */public class DMSClient { //屬性定義 //第一步:解析日誌所需屬性 //unix系統日誌檔案 private File logFile; //儲存解析後日志的檔案 private File textLogFile; //書籤檔案 private File lastPositionFile; //每次解析日誌的條目數 private int batch; //第二步:配對日誌所需要屬性 //儲存配對日誌的檔案 private File logRecFile; //儲存未配對日誌的檔案 private File loginLogFile; //第三步:傳送日誌所需要屬性 //服務端地址 private String serverHost; //服務端埠 private int serverPort; /** * 構造方法,用來初始化客戶端 * @throws Exception */ public DMSClient() throws Exception{ try { //1 解析配置檔案 Mapconfig = loadConfig(); //打樁 tln(config); //2 根據配置檔案內容初始化屬性 init(config); } catch (Exception e) { tln("初始化失敗!"); throw e; } } /** * 構造方法初始化第二步,根據配置項初始化屬性 * @param config * @throws Exception */ private void init(Mapconfig) throws Exception{ try { logFile = new File( ("logfile") ); textLogFile = new File( ("textlogfile") ); lastPositionFile = new File( ("lastpositionfile") ); batch = eInt( ("batch") ); logRecFile = new File( ("logrecfile") ); loginLogFile = new File( ("loginlogfile") ); serverHost = ("serverhost"); serverPort = eInt( ("serverport") ); } catch (Exception e) { tln("初始化屬性失敗!"); tStackTrace(); throw e; } } /** * 構造方法初始化第一步,解析配置檔案 * @return 返回的Map中儲存的是配置檔案中的 * 每一條內容,其中key:標籤的名字, * value為標籤中間的文字 * @throws Exception */ private MaploadConfig() throws Exception{ try { SAXReader reader = new SAXReader(); Document doc = (new File("")); Element root = ootElement(); Mapconfig = new HashMap(); /* * 獲取標籤中的所有子標籤 * 並將每一個子標籤的名字作為key,中間的 * 文字作為value存入Map集合 */ Listlist = ents(); for(Element e : list){ String key = ame(); String value = extTrim(); (key, value); } return config; } catch (Exception e) { tln("解析配置檔案異常!"); tStackTrace(); throw e; } } /** * 客戶端開始工作的方法 * 迴圈執行三步: * 1:解析日誌 * 2:配對日誌 * 3:傳送日誌 */ public void start(){ parseLogs(); matchLogs(); sendLogs();// while(true){// //解析日誌// if(!parseLogs()){// continue;// }// //配對日誌// if(!matchLogs()){// continue;// }// //傳送日誌// sendLogs();// } } /** * 第三步:傳送日誌 * @return true:傳送成功 * false:傳送失敗 */ private boolean sendLogs(){ /* * 實現思路: * 將logRecFile檔案中的所有配對日誌讀取 * 出來然後連線上服務端併發送過去,若服務端 * 全部接收,就可以將該檔案刪除,表示傳送 * 完畢了。 * 實現步驟: * 1:logRecFile檔案必須存在 * 2:將所有配對日誌讀取出來並存入一個集合 * 等待發送 * 3:通過Socket連線服務端 * 4:建立輸出流 * 5:順序將所有配對日誌按行傳送給服務端 * 6:單獨傳送一個字串"OVER"表示所有日誌 * 均已傳送完畢 * 7:建立輸入流 * 8:讀取服務端傳送回來的'響應字串 * 9:若響應的字串為"OK",表示服務端正常 * 接收了所有日誌,這時就可以將logRecFile * 檔案刪除並返回true表示傳送完畢。 * */ Socket socket = null; try { //1 if(!ts()){ tln(logRecFile+"不存在!"); return false; } //2 Listmatches = LogRec(logRecFile); //3 socket = new Socket(serverHost,serverPort); //4 PrintWriter pw = new PrintWriter( new OutputStreamWriter( utputStream(),"UTF-8" ) ); //5 for(String log : matches){ tln(log); } //6 tln("OVER"); h(); //7 BufferedReader br = new BufferedReader( new InputStreamReader( nputStream(),"UTF-8" ) ); //8 String response = Line(); //9 if("OK"ls(response)){ logRecFile.(); return true; }else{ tln("傳送日誌失敗!"); return false; } } catch (Exception e) { tln("傳送日誌失敗!"); tStackTrace(); } finally{ if(socket != null){ try { e(); } catch (IOException e) { tStackTrace(); } } } return false; } /** * 第二步:配對日誌 * @return true:配對成功 * false:配對失敗 */ private boolean matchLogs(){ /* * 實現思路: * 將第一步解析的新日誌,與上次為配對成功 * 的登入日誌全部讀取出來,然後再按照user, * pid相同,type一個是7,一個是8進行配對。 * 只要能找到型別為8的,一定可以找到一個 * 能與之配對的登入日誌。 * * 實現步驟: * 1:必要的判斷 * 1.1:logRecFile是否存在,存在則不再 * 進行新的配對工作,避免覆蓋。 * 1.2:textLogFile檔案必須存在。 * 2:讀取textLogFile將日誌讀取出來,並 * 存入到集合中。(若干LogData例項) * 3:若loginLogFile檔案若存在,則說明 * 有上次未配對成功的日誌,也將其讀取 * 出來存入集合等待一起配對 * 4:配對工作 * 4.1:建立一個集合,用於儲存所有配對日誌 * 4.2:建立兩個Map分別儲存登入日誌與登出日誌 * 4.3:遍歷所有待配對的日誌,按照登入與登出 * 分別存入兩個Map中, * 其中key:user,pid * value:LogData例項 * 4.4:遍歷登出Map,並根據每條登出日誌的key * 去登入Map中找到對應的登入日誌,並 * 以一個LogRec例項儲存該配對日誌,然後 * 存入配對日誌的集合中。並將該配對日誌 * 中的登入日誌從登入Map中刪除。這樣一來 * 登入Map中應當只剩下沒有配對的了。 * 5:將配對日誌寫入到logRecFile中 * 6:將所有未配對日誌寫入到loginLogFile中 * 7:將textLogFile檔案刪除 * 8:返回true,表示配對完畢 * */ try { //1 //1.1 if(ts()){ return true; } //1.2 if(!ts()){ tln(textLogFile+"不存在!"); return false; } //2 Listlist = LogData(textLogFile); //3 if(ts()){ ll( LogData(loginLogFile) ); } //4 //4.1 Listmatches = new ArrayList(); //4.2 MaploginMap = new HashMap(); MaplogoutMap = new HashMap(); //4.3 for(LogData logData : list){ String key = ser()+","+ id(); if(ype()==_LOGIN){ (key, logData); }else if(ype()==_LOGOUT){ (key, logData); } } //4.4 Set<Entry> entrySet = ySet(); for(Entrye : entrySet){ LogData logout = alue(); LogData login = ve(ey()); LogRec logRec = new LogRec(login,logout); (logRec); } //5 Collection(matches, logRecFile); //6 Collection( es(),loginLogFile ); //7 textLogFile.(); //8 return true; } catch (Exception e) { tln("配對日誌失敗!"); tStackTrace(); } return false; } /** * 第一步:解析日誌 * @return true:解析成功 * false:解析失敗 */ private boolean parseLogs(){ /* * 實現思路: * 迴圈讀取batch條日誌,然後將每條日誌中的 * 5個資訊解析出來,最終組成一個字串,以 * 行為單位,寫入到textLogFile檔案中 * * 實現步驟: * 1:必要的判斷工作 * 1.1:為了避免解析的日誌還沒有被使用,而 * 第一步又重複執行導致之前日誌被覆蓋 * 的問題,這裡需要判斷,若儲存解析後 * 的日誌檔案存在,則第一步不再執行。 * 該日誌檔案會在第二步配對完畢後刪除。 * 1.2:logFile檔案必須存在(wtmpx檔案) * 1.3:是否還有日誌可以解析 * 2:建立RandomAccessFile來讀取logFile * 3:將指標移動到上次最後讀取的位置,準備 * 開始新的解析工作 * 4:解析工作 * 4.1:建立一個List集合,用於儲存解析後 * 的每一條日誌(LogData例項) * 4.2:迴圈batch次,解析每條日誌中的 * 5項內容(user,pid,type,time,host) * 並用一個LogData例項儲存,然後將 * 該LogData例項存入集合 * 5:將集合中的所有的日誌以行為單位儲存到 * textLogFile中 * 6:儲存書籤資訊 * 7:返回true,表示工作完畢 * */ RandomAccessFile raf = null; try { //1 //1.1 if(ts()){ return true; } //1.2 if(!ts()){ tln(logFile+"不存在!"); return false; } //1.3 long lastPosition = hasLogs(); //打樁// tln(// "lastPosition:"+lastPosition// ); if(lastPosition<0){ tln("沒有日誌可以解析了!"); return false; } //2 raf = new RandomAccessFile(logFile,"r"); //3 (lastPosition); //4 Listlist = new ArrayList(); for(int i=0;i<batch;i++){ //每次解析前都判斷是否還有日誌可以解析 if(th()-lastPosition<_length 5="" 6="" 7="" user="String(" string="" _length="" pid="Int();" int="" type="Short();" short="" time="Int();" host="String(" _length="" logdata="" log="new" lastposition="Long(lastPositionFile);" return="" catch="" exception="" raf="" try="" ioexception="" private="" long="" -lastposition="">=_LENGTH){ return lastPosition; } } catch (Exception e) { tStackTrace(); } return -1; } public static void main(String[] args) { try { DMSClient client = new DMSClient(); t(); } catch (Exception e) { tln("客戶端執行失敗!"); } }}

  3.

package ; import eredReader;import ;import InputStream;import tStreamReader;import tWriter;import omAccessFile;import yList;import ection;import ; import ata; /** * 該類是一個工具類,負責客戶端的IO操作 * @author Administrator * */public class IOUtil { /** * 從給定的檔案中讀取每一行字串(配對日誌) * 並存入一個集合後返回 * @param file * @return * @throws Exception */ public static ListloadLogRec(File file) throws Exception{ BufferedReader br = null; try { br = new BufferedReader( new InputStreamReader( new FileInputStream( file ) ) ); Listlist = new ArrayList(); String line = null; while((line = Line())!=null){ (line); } return list; } catch (Exception e) { tStackTrace(); throw e; } finally{ if(br != null){ e(); } } } /** * 從給定的檔案中讀取每一條配對日誌,並存入 * 一個集合中然後返回。 * @param file * @return * @throws Exception */ public static ListloadLogData(File file) throws Exception{ BufferedReader br = null; try { br = new BufferedReader( new InputStreamReader( new FileInputStream( file ) ) ); Listlist = new ArrayList(); String line = null; while((line = Line())!=null){ LogData logData = new LogData(line); (logData); } return list; } catch (Exception e) { tStackTrace(); throw e; } finally{ if(br!=null){ e(); } } } /** * 將指定的long值以字串的形式寫入到 * 給定檔案的第一行 * @param l * @param file * @throws Exception */ public static void saveLong( long lon,File file) throws Exception{ PrintWriter pw = null; try { pw = new PrintWriter(file); tln(lon); } catch (Exception e) { tStackTrace(); throw e; } finally{ if(pw != null){ e(); } } } /** * 將集合中每個元素的toString方法返回的字串 * 以行為單位寫入到指定檔案中。 * @param c * @param file * @throws Exception */ public static void saveCollection( Collection c,File file) throws Exception{ PrintWriter pw = null; try { pw = new PrintWriter(file); for(Object o : c){ tln(o); } } catch (Exception e) { tStackTrace(); throw e; } finally{ if(pw != null){ e(); } } } /** * 從給定的RandomAccessFile當前位置開始連續 * 讀取length個位元組,並轉換為字串後返回 * @param raf * @param length * @return * @throws Exception */ public static String readString( RandomAccessFile raf,int length) throws Exception{ try { byte[] data = new byte[length]; (data); return new String(data,"ISO8859-1"); } catch (Exception e) { tStackTrace(); throw e; } } /** * 從給定檔案中讀取第一行字串,然後將其 * 轉換為一個long值後返回 * @param file * @return * @throws Exception */ public static long readLong(File file) throws Exception{ BufferedReader br = null; try { br = new BufferedReader( new InputStreamReader( new FileInputStream( file ) ) ); String line = Line(); return eLong(line); } catch (Exception e) { tStackTrace(); throw e; } finally{ if(br != null){ e(); } } }}

  4.

<"1.0" encoding="UTF-8">wtmpx10localhost8088

5.

<"1.0" encoding="UTF-8">308088