版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
本文格式為Word版,下載可任意編輯——java讀取用戶登入退出日志上傳服務(wù)端java讀取用戶登入退出日志上傳服務(wù)端
概括實(shí)現(xiàn)代碼:
1.DMSServer.java
packagecom.dms;importjava.io.BufferedReader;importjava.io.File;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.OutputStreamWriter;importjava.io.PrintWriter;.ServerSocket;.Socket;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importjava.util.concurrent.BlockingQueue;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.LinkedBlockingQueue;importorg.dom4j.Document;importorg.dom4j.Element;importorg.dom4j.io.SAXReader;/***DMS服務(wù)端,用來(lái)接收每個(gè)客戶端發(fā)送過(guò)來(lái)的*配對(duì)日志并保存在本地文件中*@authorAdministrator**/publicclassDMSServer//屬性定義//用來(lái)接收客戶端連接的服務(wù)端的ServerSocketprivateServerSocketserver;//用來(lái)管理處理客戶端苦求的線程的線程池privateExecutorServicethreadPool;//保存全體客戶端發(fā)送過(guò)來(lái)配對(duì)日志的文件privateFileserverLogFile;//消息隊(duì)列privateBlockingQueuemessageQueue=newLinkedBlockingQueue;publicDMSServerthrowsExceptiontrySystem.out.println服務(wù)端正在初始化...;//1解析配置文件server-config.xmlMapconfig=loadConfig;//2根據(jù)配置文件內(nèi)容初始化屬性initconfig;System.out.println服務(wù)端初始化完畢...;catchExceptioneSystem.out.println初始化服務(wù)端失敗!;throwe;/***構(gòu)造方法初始化第一步,解析配置文件*@return返回的Map中保存的是配置文件中的*每一條內(nèi)容,其中key:標(biāo)簽的名字,*value為標(biāo)簽中間的文本*@throwsException*/privateMaploadConfigthrowsExceptiontrySAXReaderreader=newSAXReader;Documentdoc=reader.readnewFileserver-config.xml;Elementroot=doc.getRootElement;Mapconfig=newHashMap;/**獲取標(biāo)簽中的全體子標(biāo)簽*并將每一個(gè)子標(biāo)簽的名字作為key,中間的*文本作為value存入Map集合*/Listlist=root.elements;forElemente:listStringkey=e.getName;Stringvalue=e.getTextTrim;config.putkey,value;returnconfig;catchExceptioneSystem.out.println解析配置文件奇怪!;e.printStackTrace;throwe;/***構(gòu)造方法初始化其次步,根據(jù)配置項(xiàng)初始化屬性*@paramconfig*@throwsException*/privatevoidinitMapconfigthrowsException/**用配置文件中的初始化屬性:serverLogFile*用配置文件中的初始化屬性:threadPool,這里創(chuàng)造固定大小線程池。該值作為線程池線程數(shù)量*用配置文件中的初始化屬性:server,這里這個(gè)值為ServerSocket的服務(wù)端口*/this.server=newServerSocketInteger.parseIntconfig.getserverport;this.serverLogFile=newFileconfig.getlogrecfile;this.threadPool=Executors.newFixedThreadPoolInteger.parseIntconfig.getthreadsum;/***服務(wù)端開(kāi)頭工作的方法*@throwsException*/publicvoidstartthrowsException/**實(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ù)交給線程池*使其調(diào)配線程來(lái)處理與該客戶端的交互。**/trySystem.out.println服務(wù)端開(kāi)頭工作...;SaveLogHandlerslh=newSaveLogHandler;newThreadslh.start;whiletrueSocketsocket=server.accept;threadPool.executenewClientHandlersocket;catchExceptionee.printStackTrace;throwe;publicstaticvoidmainString[]argstryDMSServerserver=newDMSServer;server.start;catchExceptioneSystem.out.println啟動(dòng)服務(wù)端失敗!;/***該線程負(fù)責(zé)從消息隊(duì)列中取出每一條配對(duì)日志,*并存入到serverLogFile文件*@authorAdministrator**/privateclassSaveLogHandlerimplementsRunnablepublicvoidrunPrintWriterpw=null;trypw=newPrintWriternewFileOutputStreamserverLogFile,true;whiletrueifmessageQueue.size0pw.printlnmessageQueue.poll;elsepw.flush;Thread.sleep500;catchExceptionee.printStackTrace;finallyifpw!=nullpw.close;/***處理一個(gè)指定客戶端苦求*@authorAdministrator**/privateclassClientHandlerimplementsRunnableprivateSocketsocket;publicClientHandlerSocketsocketthis.socket=socket;publicvoidrun/**思路:*首先接收客戶端發(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*/PrintWriterpw=null;try//1pw=newPrintWriternewOutputStreamWritersocket.getOutputStream,UTF-8;//2BufferedReaderbr=newBufferedReadernewInputStreamReadersocket.getInputStream,UTF-8;//3Stringmessage=null;whilemessage=br.readLine!=nullifOVER.equalsmessagebreak;//將該日志寫(xiě)入文件保存messageQueue.offermessage;//4pw.printlnOK;pw.flush;catchExceptionee.printStackTrace;pw.printlnERROR;pw.flush;finallytry//與客戶端斷開(kāi)連接釋放資源socket.close;catchIOExceptionee.printStackTrace;
2.DMSClient.java
packagecom.dms;importjava.io.BufferedReader;importjava.io.File;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.OutputStreamWriter;importjava.io.PrintWriter;importjava.io.RandomAccessFile;.Socket;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importjava.util.Map.Entry;importjava.util.Set;importorg.dom4j.Document;importorg.dom4j.Element;importorg.dom4j.io.SAXReader;importcom.dms.bo.LogData;importcom.dms.bo.LogRec;/***該客戶端運(yùn)行在給用戶供給unix服務(wù)的服務(wù)器上。*用來(lái)讀取并收集該服務(wù)器上用戶的上下線信息,并*舉行配對(duì)整理后發(fā)送給服務(wù)端匯總。*@authorAdministrator**/publicclassDMSClient//屬性定義//第一步:解析日志所需屬性//unix系統(tǒng)日志文件privateFilelogFile;//保存解析后日志的文件privateFiletextLogFile;//書(shū)簽文件privateFilelastPositionFile;//每次解析日志的條目數(shù)privateintbatch;//其次步:配對(duì)日志所需要屬性//保存配對(duì)日志的文件privateFilelogRecFile;//保存未配對(duì)日志的文件privateFileloginLogFile;//第三步:發(fā)送日志所需要屬性//服務(wù)端地址privateStringserverHost;//服務(wù)端端口privateintserverPort;/***構(gòu)造方法,用來(lái)初始化客戶端*@throwsException*/publicDMSClientthrowsExceptiontry//1解析配置文件config.xmlMapconfig=loadConfig;//打樁System.out.printlnconfig;//2根據(jù)配置文件內(nèi)容初始化屬性initconfig;catchExceptioneSystem.out.println初始化失敗!;throwe;/***構(gòu)造方法初始化其次步,根據(jù)配置項(xiàng)初始化屬性*@paramconfig*@throwsException*/privatevoidinitMapconfigthrowsExceptiontrylogFile=newFileconfig.getlogfile;textLogFile=newFileconfig.gettextlogfile;lastPositionFile=newFileconfig.getlastpositionfile;batch=Integer.parseIntconfig.getbatch;logRecFile=newFileconfig.getlogrecfile;loginLogFile=newFileconfig.getloginlogfile;serverHost=config.getserverhost;serverPort=Integer.parseIntconfig.getserverport;catchExceptioneSystem.out.println初始化屬性失敗!;e.printStackTrace;throwe;/***構(gòu)造方法初始化第一步,解析配置文件*@return返回的Map中保存的是配置文件中的*每一條內(nèi)容,其中key:標(biāo)簽的名字,*value為標(biāo)簽中間的文本*@throwsException*/privateMaploadConfigthrowsExceptiontrySAXReaderreader=newSAXReader;Documentdoc=reader.readnewFileconfig.xml;Elementroot=doc.getRootElement;Mapconfig=newHashMap;/**獲取標(biāo)簽中的全體子標(biāo)簽*并將每一個(gè)子標(biāo)簽的名字作為key,中間的*文本作為value存入Map集合*/Listlist=root.elements;forElemente:listStringkey=e.getName;Stringvalue=e.getTextTrim;config.putkey,value;returnconfig;catchExceptioneSystem.out.println解析配置文件奇怪!;e.printStackTrace;throwe;/***客戶端開(kāi)頭工作的方法*循環(huán)執(zhí)行三步:*1:解析日志*2:配對(duì)日志*3:發(fā)送日志*/publicvoidstartparseLogs;matchLogs;sendLogs;//whiletrue////解析日志//if!parseLogs//continue;//////配對(duì)日志//if!matchLogs//continue;//////發(fā)送日志//sendLogs;///***第三步:發(fā)送日志*@returntrue:發(fā)送告成*false:發(fā)送失敗*/privatebooleansendLogs/**實(shí)現(xiàn)思路:*將logRecFile文件中的全體配對(duì)日志讀取*出來(lái)然后連接上服務(wù)端并發(fā)送過(guò)去,若服務(wù)端*全部接收,就可以將該文件刪除,表示發(fā)送*完畢了。*實(shí)現(xiàn)步驟:*1:logRecFile文件務(wù)必存在*2:將全體配對(duì)日志讀取出來(lái)并存入一個(gè)集合*等待發(fā)送*3:通過(guò)Socket連接服務(wù)端*4:創(chuàng)造輸出流*5:依次將全體配對(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ā)送完畢。**/Socketsocket=null;try//1if!logRecFile.existsSystem.out.printlnlogRecFile+不存在!;returnfalse;//2Listmatches=IOUtil.loadLogReclogRecFile;//3socket=newSocketserverHost,serverPort;//4PrintWriterpw=newPrintWriternewOutputStreamWritersocket.getOutputStream,UTF-8;//5forStringlog:matchespw.printlnlog;//6pw.printlnOVER;pw.flush;//7BufferedReaderbr=newBufferedReadernewInputStreamReadersocket.getInputStream,UTF-8;//8Stringresponse=br.readLine;//9ifOK.equalsresponselogRecFile.;returntrue;elseSystem.out.println發(fā)送日志失敗!;returnfalse;catchExceptioneSystem.out.println發(fā)送日志失敗!;e.printStackTrace;finallyifsocket!=nulltrysocket.close;catchIOExceptionee.printStackTrace;returnfalse;/***其次步:配對(duì)日志*@returntrue:配對(duì)告成*false:配對(duì)失敗*/privatebooleanmatchLogs/**實(shí)現(xiàn)思路:*將第一步解析的新日志,與上次為配對(duì)告成*的登入日志全部讀取出來(lái),然后再按照user,*pid一致,type一個(gè)是7,一個(gè)是8舉行配對(duì)。*只要能找到類型為8的,確定可以找到一個(gè)*能與之配對(duì)的登入日志。**實(shí)現(xiàn)步驟:*1:必要的判斷*1.1:logRecFile是否存在,存在那么不再*舉行新的配對(duì)工作,制止籠罩。*1.2:textLogFile文件務(wù)必存在。*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.1iflogRecFile.existsreturntrue;//1.2if!textLogFile.existsSystem.out.printlntextLogFile+不存在!;returnfalse;//2Listlist=IOUtil.loadLogDatatextLogFile;//3ifloginLogFile.existslist.addAllIOUtil.loadLogDataloginLogFile;//4//4.1Listmatches=newArrayList;//4.2MaploginMap=newHashMap;MaplogoutMap=newHashMap;//4.3forLogDatalogData:listStringkey=logData.getUser+,+logData.getPid;iflogData.getType==LogData.TYPE_LOGINloginMap.putkey,logData;elseiflogData.getType==LogData.TYPE_LOGOUTlogoutMap.putkey,logData;//4.4SetEntryentrySet=logoutMap.entrySet;forEntrye:entrySetLogDatalogout=e.getValue;LogDatalogin=loginMap.removee.getKey;LogReclogRec=newLogReclogin,logout;matches.addlogRec;//5IOUtil.saveCollectionmatches,logRecFile;//6IOUtil.saveCollectionloginMap.values,loginLogFile;//7textLogFile.;//8returntrue;catchExceptioneSystem.out.println配對(duì)日志失敗!;e.printStackTrace;returnfalse;/***第一步:解析日志*@returntrue:解析告成*false:解析失敗*/privatebooleanparseLogs/**實(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文件務(wù)必存在wtmpx文件*1.3:是否還有日志可以解析*2:創(chuàng)造RandomAccessFile來(lái)讀取logFile*3:將指針移動(dòng)到上次結(jié)果讀取的位置,打定*開(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,表示工作完畢**/RandomAccessFileraf=null;try//1//1.1iftextLogFile.existsreturntrue;//1.2if!logFile.existsSystem.out.printlnlogFile+不存在!;returnfalse;//1.3longlastPosition=hasLogs;//打樁//System.out.println//lastPosition:+lastPosition//;iflastPosition0System.out.println沒(méi)有日志可以解析了!;returnfalse;//2raf=newRandomAccessFilelogFile,r;//3raf.seeklastPosition;//4Listlist=newArrayList;forinti=0;ibatch;i++//每次解析前都判斷是否還有日志可以解析iflogFile.length-lastPosition=LogData.LOG_LENGTHreturnlastPosition;catchExceptionee.printStackTrace;return-1;publicstaticvoidmainString[]argstryDMSClientclient=newDMSClient;client.start;catchExceptioneSystem.out.println客戶端運(yùn)行失敗!;
3.IOUtil.java
packagecom.dms;importjava.io.BufferedReader;importjava.io.File;importjava.io.FileInputStream;importjava.io.InputStreamReader;importjava.io.PrintWriter;importjava.io.RandomAccessFile;importjava.util.ArrayList;importjava.util.Collection;importjava.util.List;importcom.dms.bo.LogData;/***該類是一個(gè)工具類,負(fù)責(zé)客戶端的IO操作*@authorAdministrator**/publicclassIOUtil/***從給定的文件中讀取每一行字符串配對(duì)日志*并存入一個(gè)集合后返回*@paramfile*@return*@throwsException*/publicstaticListloadLogRecFilefilethrowsExceptionBufferedReaderbr=null;trybr=newBufferedReadernewInputStreamReadernewFileInputStreamfile;Listlist=newArrayList;Stringline=null;whileline=br.readLine!=nulllist.addline;returnlist;catchExceptionee.printStackTrace;throwe;finallyifbr!=nullbr.close;/***從給定的文件中讀取每一條配對(duì)日志,并存入*一個(gè)集合中然后返回。*@paramfile*@return*@throwsException*/publicstaticListloadLogDataFilefilethrowsExceptionBufferedReaderbr=null;trybr=newBufferedReadernewInputStreamReadernewFileInputStreamfile;Listlist=newArrayList;Stringline=null;whileline=br.readLine!=nullLogDatalogData=newLogDataline;list.addlogData;returnlist;catchExceptionee.printStackTrace;throwe;finallyifbr!=nullbr.close;/***將指定的long值以字符串的形式寫(xiě)入到*給定文件的第一行*@paraml*@paramfile*@throwsException*/publicstaticvoidsaveLonglonglon,FilefilethrowsEx
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025-2030湘菜餐飲碳排放測(cè)算與綠色轉(zhuǎn)型路徑
- 2025-2030湘菜社區(qū)餐飲模式創(chuàng)新與便民服務(wù)實(shí)踐
- 2025-2030湘菜與酒水搭配消費(fèi)習(xí)慣及聯(lián)合營(yíng)銷機(jī)會(huì)
- 2025-2030消防監(jiān)控子系統(tǒng)行業(yè)市場(chǎng)供需研究及投資立體規(guī)劃研究資料
- 2025-2030消防安全設(shè)備制造行業(yè)技術(shù)標(biāo)準(zhǔn)及行業(yè)規(guī)范與安全保障分析
- 2025-2030消費(fèi)級(jí)電子產(chǎn)品屏下指紋識(shí)別技術(shù)成熟度評(píng)估
- 2025-2030消費(fèi)級(jí)無(wú)人機(jī)市場(chǎng)監(jiān)管政策變化對(duì)行業(yè)影響分析報(bào)告
- 2025-2030消費(fèi)級(jí)基因檢測(cè)市場(chǎng)教育現(xiàn)狀與產(chǎn)品差異化競(jìng)爭(zhēng)報(bào)告
- 2025-2030消費(fèi)級(jí)AR眼鏡顯示技術(shù)路線與用戶體驗(yàn)優(yōu)化分析報(bào)告
- 2025-2030消費(fèi)級(jí)AR眼鏡光學(xué)顯示方案對(duì)比與沉浸式體驗(yàn)優(yōu)化戰(zhàn)略咨詢報(bào)告
- 影視表演知識(shí)培訓(xùn)課件
- 石墨烯神經(jīng)保護(hù)-洞察與解讀
- 車輛中心面試車輛管理題
- 消除艾滋病、梅毒和乙肝母嬰傳播鄉(xiāng)村醫(yī)生培訓(xùn)會(huì)-課件
- 制造企業(yè)總經(jīng)理年終總結(jié)
- 供應(yīng)室去污區(qū)工作總結(jié)
- 隧道防水知識(shí)培訓(xùn)課件
- 學(xué)堂在線 雨課堂 學(xué)堂云 中國(guó)傳統(tǒng)藝術(shù)-篆刻、書(shū)法、水墨畫(huà)體驗(yàn)與欣賞 章節(jié)測(cè)試答案
- 陰莖假體植入術(shù)改良方案-洞察及研究
- 神經(jīng)外科規(guī)范化培訓(xùn)體系綱要
- 互助與團(tuán)隊(duì)精神主題班會(huì)課件
評(píng)論
0/150
提交評(píng)論