當前位置:學者齋 >

計算機 >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

  • 文章版權屬於文章作者所有,轉載請註明 https://xuezhezhai.com/zh-hk/jsj/java/2xj1pj.html