亚洲精品中文字幕无乱码_久久亚洲精品无码AV大片_最新国产免费Av网址_国产精品3级片

java語(yǔ)言

java讀取用戶登入退出日志上傳服務(wù)端

時(shí)間:2024-10-09 09:53:35 java語(yǔ)言 我要投稿
  • 相關(guān)推薦

java讀取用戶登入退出日志上傳服務(wù)端

  具體實(shí)現(xiàn)代碼:

java讀取用戶登入退出日志上傳服務(wù)端

  1. DMSServer.java

  package com.dms; import java.io.BufferedReader;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.concurrent.BlockingQueue;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.LinkedBlockingQueue; import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.io.SAXReader; /** * DMS服務(wù)端,用來(lái)接收每個(gè)客戶端發(fā)送過(guò)來(lái)的 * 配對(duì)日志并保存在本地文件中 * @author Administrator * */public class DMSServer { //屬性定義 //用來(lái)接收客戶端連接的服務(wù)端的ServerSocket private ServerSocket server; //用來(lái)管理處理客戶端請(qǐng)求的線程的線程池 private ExecutorService threadPool; //保存所有客戶端發(fā)送過(guò)來(lái)配對(duì)日志的文件 private File serverLogFile; //消息隊(duì)列 private BlockingQueuemessageQueue = new LinkedBlockingQueue(); public DMSServer() throws Exception{ try { System.out.println("服務(wù)端正在初始化..."); //1 解析配置文件server-config.xml Mapconfig = loadConfig(); //2 根據(jù)配置文件內(nèi)容初始化屬性 init(config); System.out.println("服務(wù)端初始化完畢..."); } catch (Exception e) { System.out.println("初始化服務(wù)端失敗!"); throw e; } } /** * 構(gòu)造方法初始化第一步,解析配置文件 * @return 返回的Map中保存的是配置文件中的 * 每一條內(nèi)容,其中key:標(biāo)簽的名字, * value為標(biāo)簽中間的文本 * @throws Exception */ private MaploadConfig() throws Exception{ try { SAXReader reader = new SAXReader(); Document doc = reader.read(new File("server-config.xml")); Element root = doc.getRootElement(); Mapconfig = new HashMap(); /* * 獲取標(biāo)簽中的所有子標(biāo)簽 * 并將每一個(gè)子標(biāo)簽的名字作為key,中間的 * 文本作為value存入Map集合 */ Listlist = root.elements(); for(Element e : list){ String key = e.getName(); String value = e.getTextTrim(); config.put(key, value); } return config; } catch (Exception e) { System.out.println("解析配置文件異常!"); e.printStackTrace(); throw e; } } /** * 構(gòu)造方法初始化第二步,根據(jù)配置項(xiàng)初始化屬性 * @param config * @throws Exception */ private void init(Mapconfig) throws Exception{ /* * 用配置文件中的初始化屬性:serverLogFile * 用配置文件中的初始化屬性:threadPool,這里創(chuàng)建固定大小線程池。該值作為線程池線程數(shù)量 * 用配置文件中的初始化屬性:server,這里這個(gè)值為ServerSocket的服務(wù)端口 */ this.server = new ServerSocket( Integer.parseInt(config.get("serverport")) ); this.serverLogFile = new File( config.get("logrecfile") ); this.threadPool = Executors.newFixedThreadPool( Integer.parseInt(config.get("threadsum")) ); } /** * 服務(wù)端開(kāi)始工作的方法 * @throws Exception */ public void start() throws Exception{ /* * 實(shí)現(xiàn)要求: * 首先單獨(dú)啟動(dòng)一個(gè)線程,用來(lái)運(yùn)行SaveLogHandler * 這個(gè)任務(wù),目的是保存所有配對(duì)日志 * 然后開(kāi)始循環(huán)監(jiān)聽(tīng)服務(wù)端端口,一旦一個(gè)客戶端連接了, * 就實(shí)例化一個(gè)ClientHander,然后將該任務(wù)交給線程池 * 使其分配線程來(lái)處理與該客戶端的交互。 * */ try { System.out.println("服務(wù)端開(kāi)始工作..."); SaveLogHandler slh=new SaveLogHandler(); new Thread(slh).start(); while(true){ Socket socket=server.accept(); threadPool.execute(new ClientHandler(socket)); } } catch (Exception e) { e.printStackTrace(); throw e; } } public static void main(String[] args) { try { DMSServer server = new DMSServer(); server.start(); } catch (Exception e) { System.out.println("啟動(dòng)服務(wù)端失敗!"); } } /** * 該線程負(fù)責(zé)從消息隊(duì)列中取出每一條配對(duì)日志, * 并存入到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(messageQueue.size()>0){ pw.println(messageQueue.poll()); }else{ pw.flush(); Thread.sleep(500); } } } catch (Exception e) { e.printStackTrace(); } finally{ if(pw != null){ pw.close(); } } } } /** * 處理一個(gè)指定客戶端請(qǐng)求 * @author Administrator * */ private class ClientHandler implements Runnable{ private Socket socket; public ClientHandler(Socket socket){ this.socket = socket; } public void run(){ /* * 思路: * 首先接收客戶端發(fā)送過(guò)來(lái)的所有配對(duì)日志, * 直到讀取到"OVER"為止,然后將這些配對(duì) * 日志保存到本地的文件中,并回復(fù)客戶端 * "OK" * 執(zhí)行步驟: * 1:通過(guò)Socket創(chuàng)建輸出流,用來(lái)給客戶端 * 發(fā)送響應(yīng) * 2:通過(guò)Socket創(chuàng)建輸入流,讀取客戶端發(fā)送 * 過(guò)來(lái)的日志 * 3:循環(huán)讀取客戶端發(fā)送過(guò)來(lái)的每一行字符串,并 * 先判斷是否為字符串"OVER",若不是,則是 * 一條配對(duì)日志,那么保存到本地文件,若是, * 則停止讀取。 * 4:成功讀取所有日志后回復(fù)客戶端"OK" */ PrintWriter pw = null; try { //1 pw = new PrintWriter( new OutputStreamWriter( socket.getOutputStream(),"UTF-8" ) ); //2 BufferedReader br = new BufferedReader( new InputStreamReader( socket.getInputStream(),"UTF-8" ) ); //3 String message = null; while((message = br.readLine())!=null){ if("OVER".equals(message)){ break; } //將該日志寫(xiě)入文件保存 messageQueue.offer(message); } //4 pw.println("OK"); pw.flush(); } catch (Exception e) { e.printStackTrace(); pw.println("ERROR"); pw.flush(); } finally{ try { //與客戶端斷開(kāi)連接釋放資源 socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }}

  2. DMSClient.java

  package com.dms; import java.io.BufferedReader;import java.io.File;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.io.RandomAccessFile;import java.net.Socket;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Map.Entry;import java.util.Set; import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.io.SAXReader; import com.dms.bo.LogData;import com.dms.bo.LogRec; /** * 該客戶端運(yùn)行在給用戶提供unix服務(wù)的服務(wù)器上。 * 用來(lái)讀取并收集該服務(wù)器上用戶的上下線信息,并 * 進(jìn)行配對(duì)整理后發(fā)送給服務(wù)端匯總。 * @author Administrator * */public class DMSClient { //屬性定義 //第一步:解析日志所需屬性 //unix系統(tǒng)日志文件 private File logFile; //保存解析后日志的文件 private File textLogFile; //書(shū)簽文件 private File lastPositionFile; //每次解析日志的條目數(shù) private int batch; //第二步:配對(duì)日志所需要屬性 //保存配對(duì)日志的文件 private File logRecFile; //保存未配對(duì)日志的文件 private File loginLogFile; //第三步:發(fā)送日志所需要屬性 //服務(wù)端地址 private String serverHost; //服務(wù)端端口 private int serverPort; /** * 構(gòu)造方法,用來(lái)初始化客戶端 * @throws Exception */ public DMSClient() throws Exception{ try { //1 解析配置文件config.xml Mapconfig = loadConfig(); //打樁 System.out.println(config); //2 根據(jù)配置文件內(nèi)容初始化屬性 init(config); } catch (Exception e) { System.out.println("初始化失敗!"); throw e; } } /** * 構(gòu)造方法初始化第二步,根據(jù)配置項(xiàng)初始化屬性 * @param config * @throws Exception */ private void init(Mapconfig) throws Exception{ try { logFile = new File( config.get("logfile") ); textLogFile = new File( config.get("textlogfile") ); lastPositionFile = new File( config.get("lastpositionfile") ); batch = Integer.parseInt( config.get("batch") ); logRecFile = new File( config.get("logrecfile") ); loginLogFile = new File( config.get("loginlogfile") ); serverHost = config.get("serverhost"); serverPort = Integer.parseInt( config.get("serverport") ); } catch (Exception e) { System.out.println("初始化屬性失敗!"); e.printStackTrace(); throw e; } } /** * 構(gòu)造方法初始化第一步,解析配置文件 * @return 返回的Map中保存的是配置文件中的 * 每一條內(nèi)容,其中key:標(biāo)簽的名字, * value為標(biāo)簽中間的文本 * @throws Exception */ private MaploadConfig() throws Exception{ try { SAXReader reader = new SAXReader(); Document doc = reader.read(new File("config.xml")); Element root = doc.getRootElement(); Mapconfig = new HashMap(); /* * 獲取標(biāo)簽中的所有子標(biāo)簽 * 并將每一個(gè)子標(biāo)簽的名字作為key,中間的 * 文本作為value存入Map集合 */ Listlist = root.elements(); for(Element e : list){ String key = e.getName(); String value = e.getTextTrim(); config.put(key, value); } return config; } catch (Exception e) { System.out.println("解析配置文件異常!"); e.printStackTrace(); throw e; } } /** * 客戶端開(kāi)始工作的方法 * 循環(huán)執(zhí)行三步: * 1:解析日志 * 2:配對(duì)日志 * 3:發(fā)送日志 */ public void start(){ parseLogs(); matchLogs(); sendLogs();// while(true){// //解析日志// if(!parseLogs()){// continue;// }// //配對(duì)日志// if(!matchLogs()){// continue;// }// //發(fā)送日志// sendLogs();// } } /** * 第三步:發(fā)送日志 * @return true:發(fā)送成功 * false:發(fā)送失敗 */ private boolean sendLogs(){ /* * 實(shí)現(xiàn)思路: * 將logRecFile文件中的所有配對(duì)日志讀取 * 出來(lái)然后連接上服務(wù)端并發(fā)送過(guò)去,若服務(wù)端 * 全部接收,就可以將該文件刪除,表示發(fā)送 * 完畢了。 * 實(shí)現(xiàn)步驟: * 1:logRecFile文件必須存在 * 2:將所有配對(duì)日志讀取出來(lái)并存入一個(gè)集合 * 等待發(fā)送 * 3:通過(guò)Socket連接服務(wù)端 * 4:創(chuàng)建輸出流 * 5:順序?qū)⑺信鋵?duì)日志按行發(fā)送給服務(wù)端 * 6:單獨(dú)發(fā)送一個(gè)字符串"OVER"表示所有日志 * 均已發(fā)送完畢 * 7:創(chuàng)建輸入流 * 8:讀取服務(wù)端發(fā)送回來(lái)的響應(yīng)字符串 * 9:若響應(yīng)的字符串為"OK",表示服務(wù)端正常 * 接收了所有日志,這時(shí)就可以將logRecFile * 文件刪除并返回true表示發(fā)送完畢。 * */ Socket socket = null; try { //1 if(!logRecFile.exists()){ System.out.println(logRecFile+"不存在!"); return false; } //2 Listmatches = IOUtil.loadLogRec(logRecFile); //3 socket = new Socket(serverHost,serverPort); //4 PrintWriter pw = new PrintWriter( new OutputStreamWriter( socket.getOutputStream(),"UTF-8" ) ); //5 for(String log : matches){ pw.println(log); } //6 pw.println("OVER"); pw.flush(); //7 BufferedReader br = new BufferedReader( new InputStreamReader( socket.getInputStream(),"UTF-8" ) ); //8 String response = br.readLine(); //9 if("OK".equals(response)){ logRecFile.(); return true; }else{ System.out.println("發(fā)送日志失敗!"); return false; } } catch (Exception e) { System.out.println("發(fā)送日志失敗!"); e.printStackTrace(); } finally{ if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } return false; } /** * 第二步:配對(duì)日志 * @return true:配對(duì)成功 * false:配對(duì)失敗 */ private boolean matchLogs(){ /* * 實(shí)現(xiàn)思路: * 將第一步解析的新日志,與上次為配對(duì)成功 * 的登入日志全部讀取出來(lái),然后再按照user, * pid相同,type一個(gè)是7,一個(gè)是8進(jìn)行配對(duì)。 * 只要能找到類型為8的,一定可以找到一個(gè) * 能與之配對(duì)的登入日志。 * * 實(shí)現(xiàn)步驟: * 1:必要的判斷 * 1.1:logRecFile是否存在,存在則不再 * 進(jìn)行新的配對(duì)工作,避免覆蓋。 * 1.2:textLogFile文件必須存在。 * 2:讀取textLogFile將日志讀取出來(lái),并 * 存入到集合中。(若干LogData實(shí)例) * 3:若loginLogFile文件若存在,則說(shuō)明 * 有上次未配對(duì)成功的日志,也將其讀取 * 出來(lái)存入集合等待一起配對(duì) * 4:配對(duì)工作 * 4.1:創(chuàng)建一個(gè)集合,用于保存所有配對(duì)日志 * 4.2:創(chuàng)建兩個(gè)Map分別保存登入日志與登出日志 * 4.3:遍歷所有待配對(duì)的日志,按照登入與登出 * 分別存入兩個(gè)Map中, * 其中key:user,pid * value:LogData實(shí)例 * 4.4:遍歷登出Map,并根據(jù)每條登出日志的key * 去登入Map中找到對(duì)應(yīng)的登入日志,并 * 以一個(gè)LogRec實(shí)例保存該配對(duì)日志,然后 * 存入配對(duì)日志的集合中。并將該配對(duì)日志 * 中的登入日志從登入Map中刪除。這樣一來(lái) * 登入Map中應(yīng)當(dāng)只剩下沒(méi)有配對(duì)的了。 * 5:將配對(duì)日志寫(xiě)入到logRecFile中 * 6:將所有未配對(duì)日志寫(xiě)入到loginLogFile中 * 7:將textLogFile文件刪除 * 8:返回true,表示配對(duì)完畢 * */ try { //1 //1.1 if(logRecFile.exists()){ return true; } //1.2 if(!textLogFile.exists()){ System.out.println(textLogFile+"不存在!"); return false; } //2 Listlist = IOUtil.loadLogData(textLogFile); //3 if(loginLogFile.exists()){ list.addAll( IOUtil.loadLogData(loginLogFile) ); } //4 //4.1 Listmatches = new ArrayList(); //4.2 MaploginMap = new HashMap(); MaplogoutMap = new HashMap(); //4.3 for(LogData logData : list){ String key = logData.getUser()+","+ logData.getPid(); if(logData.getType()==LogData.TYPE_LOGIN){ loginMap.put(key, logData); }else if(logData.getType()==LogData.TYPE_LOGOUT){ logoutMap.put(key, logData); } } //4.4 Set<Entry> entrySet = logoutMap.entrySet(); for(Entrye : entrySet){ LogData logout = e.getValue(); LogData login = loginMap.remove(e.getKey()); LogRec logRec = new LogRec(login,logout); matches.add(logRec); } //5 IOUtil.saveCollection(matches, logRecFile); //6 IOUtil.saveCollection( loginMap.values(),loginLogFile ); //7 textLogFile.(); //8 return true; } catch (Exception e) { System.out.println("配對(duì)日志失敗!"); e.printStackTrace(); } return false; } /** * 第一步:解析日志 * @return true:解析成功 * false:解析失敗 */ private boolean parseLogs(){ /* * 實(shí)現(xiàn)思路: * 循環(huán)讀取batch條日志,然后將每條日志中的 * 5個(gè)信息解析出來(lái),最終組成一個(gè)字符串,以 * 行為單位,寫(xiě)入到textLogFile文件中 * * 實(shí)現(xiàn)步驟: * 1:必要的判斷工作 * 1.1:為了避免解析的日志還沒(méi)有被使用,而 * 第一步又重復(fù)執(zhí)行導(dǎo)致之前日志被覆蓋 * 的問(wèn)題,這里需要判斷,若保存解析后 * 的日志文件存在,則第一步不再執(zhí)行。 * 該日志文件會(huì)在第二步配對(duì)完畢后刪除。 * 1.2:logFile文件必須存在(wtmpx文件) * 1.3:是否還有日志可以解析 * 2:創(chuàng)建RandomAccessFile來(lái)讀取logFile * 3:將指針移動(dòng)到上次最后讀取的位置,準(zhǔn)備 * 開(kāi)始新的解析工作 * 4:解析工作 * 4.1:創(chuàng)建一個(gè)List集合,用于保存解析后 * 的每一條日志(LogData實(shí)例) * 4.2:循環(huán)batch次,解析每條日志中的 * 5項(xiàng)內(nèi)容(user,pid,type,time,host) * 并用一個(gè)LogData實(shí)例保存,然后將 * 該LogData實(shí)例存入集合 * 5:將集合中的所有的日志以行為單位保存到 * textLogFile中 * 6:保存書(shū)簽信息 * 7:返回true,表示工作完畢 * */ RandomAccessFile raf = null; try { //1 //1.1 if(textLogFile.exists()){ return true; } //1.2 if(!logFile.exists()){ System.out.println(logFile+"不存在!"); return false; } //1.3 long lastPosition = hasLogs(); //打樁// System.out.println(// "lastPosition:"+lastPosition// ); if(lastPosition<0){ System.out.println("沒(méi)有日志可以解析了!"); return false; } //2 raf = new RandomAccessFile(logFile,"r"); //3 raf.seek(lastPosition); //4 Listlist = new ArrayList(); for(int i=0;i<batch;i++){ //每次解析前都判斷是否還有日志可以解析 if(logFile.length()-lastPosition=LogData.LOG_LENGTH){ return lastPosition; } } catch (Exception e) { e.printStackTrace(); } return -1; } public static void main(String[] args) { try { DMSClient client = new DMSClient(); client.start(); } catch (Exception e) { System.out.println("客戶端運(yùn)行失敗!"); } }}

  3. IOUtil.java

  package com.dms; import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.io.RandomAccessFile;import java.util.ArrayList;import java.util.Collection;import java.util.List; import com.dms.bo.LogData; /** * 該類是一個(gè)工具類,負(fù)責(zé)客戶端的IO操作 * @author Administrator * */public class IOUtil { /** * 從給定的文件中讀取每一行字符串(配對(duì)日志) * 并存入一個(gè)集合后返回 * @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 = br.readLine())!=null){ list.add(line); } return list; } catch (Exception e) { e.printStackTrace(); throw e; } finally{ if(br != null){ br.close(); } } } /** * 從給定的文件中讀取每一條配對(duì)日志,并存入 * 一個(gè)集合中然后返回。 * @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 = br.readLine())!=null){ LogData logData = new LogData(line); list.add(logData); } return list; } catch (Exception e) { e.printStackTrace(); throw e; } finally{ if(br!=null){ br.close(); } } } /** * 將指定的long值以字符串的形式寫(xiě)入到 * 給定文件的第一行 * @param l * @param file * @throws Exception */ public static void saveLong( long lon,File file) throws Exception{ PrintWriter pw = null; try { pw = new PrintWriter(file); pw.println(lon); } catch (Exception e) { e.printStackTrace(); throw e; } finally{ if(pw != null){ pw.close(); } } } /** * 將集合中每個(gè)元素的toString方法返回的字符串 * 以行為單位寫(xiě)入到指定文件中。 * @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){ pw.println(o); } } catch (Exception e) { e.printStackTrace(); throw e; } finally{ if(pw != null){ pw.close(); } } } /** * 從給定的RandomAccessFile當(dāng)前位置開(kāi)始連續(xù) * 讀取length個(gè)字節(jié),并轉(zhuǎn)換為字符串后返回 * @param raf * @param length * @return * @throws Exception */ public static String readString( RandomAccessFile raf,int length) throws Exception{ try { byte[] data = new byte[length]; raf.read(data); return new String(data,"ISO8859-1"); } catch (Exception e) { e.printStackTrace(); throw e; } } /** * 從給定文件中讀取第一行字符串,然后將其 * 轉(zhuǎn)換為一個(gè)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 = br.readLine(); return Long.parseLong(line); } catch (Exception e) { e.printStackTrace(); throw e; } finally{ if(br != null){ br.close(); } } }}

  4. config.xml

  <"1.0" encoding="UTF-8">wtmpxlog.txtlast-position.txt10logrec.txtlogin.txtlocalhost8088

  5. server-config.xml

  <"1.0" encoding="UTF-8">server-logs.txt308088


【java讀取用戶登入退出日志上傳服務(wù)端】相關(guān)文章:

java讀取解析xml文件實(shí)例12-01

Java圖形用戶接口03-29

Java如何讀取文本文件12-15

從Java的jar文件中如何讀取數(shù)據(jù)的方法04-03

讀取用戶屬性提示“沒(méi)有啟動(dòng)服務(wù)器服務(wù)”怎么辦03-28

javasocket服務(wù)端技巧03-27

QQ的網(wǎng)絡(luò)硬盤(pán)如何上傳資源12-04

php上傳與刪除圖片的簡(jiǎn)單范例03-31

盤(pán)Linux服務(wù)端的測(cè)試及故障處理辦法03-05