嵌入式課程設(shè)計(jì)(論文)android聊天室設(shè)計(jì)_第1頁
嵌入式課程設(shè)計(jì)(論文)android聊天室設(shè)計(jì)_第2頁
嵌入式課程設(shè)計(jì)(論文)android聊天室設(shè)計(jì)_第3頁
嵌入式課程設(shè)計(jì)(論文)android聊天室設(shè)計(jì)_第4頁
嵌入式課程設(shè)計(jì)(論文)android聊天室設(shè)計(jì)_第5頁
已閱讀5頁,還剩17頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、嵌入式課程設(shè)計(jì)(論文)androidl聊天室設(shè)計(jì)學(xué) 生: 學(xué) 號:指導(dǎo)教師:李季 老師專 業(yè):計(jì)算機(jī)科學(xué)與技術(shù)重慶大學(xué)計(jì)算機(jī)學(xué)院二o一一年十二月嵌入式課程設(shè)計(jì)(論文) 中文摘要摘 要此系統(tǒng)設(shè)計(jì)了一個(gè)基于android系統(tǒng)與pc之間的通信,采用socket流式套接字進(jìn)行網(wǎng)絡(luò)通信。其中android系統(tǒng)的模擬器作為客戶端,客戶端采用獲取手機(jī)號碼作為該客戶端的唯一標(biāo)識,pc作為服務(wù)器端。其中客戶端的設(shè)計(jì)過程中主要用chatclientactivity 文件實(shí)現(xiàn)客戶端的各個(gè)widget的功能以及利用socket向服務(wù)器端發(fā)送和接受服務(wù)器端的消息。服務(wù)器端主要用serverthread 服務(wù)器線程初始化

2、serversocket并將對客戶端監(jiān)聽到得socket封裝到clientthread線程中并將該線程存放到vector數(shù)組用于服務(wù)器與指定客戶端交互,以及啟動broadcast線程和clientthread線程,以及將,其中clientthread線程主要用于將監(jiān)聽到客戶端發(fā)送的消息存放到消息隊(duì)列并將其保存在sql2000數(shù)據(jù)庫中以及根據(jù)分類顯示在控制臺上,broadcast線程主要獲取消息隊(duì)列中的消息并根據(jù)消息的性質(zhì)確定是否將此消息廣播到所有在線客戶端或是發(fā)送到某些指定的客戶端。startserver主要用于啟動serverthread線程,即啟動整個(gè)服務(wù)器。dodatabase主要用于連

3、接數(shù)據(jù)庫和實(shí)現(xiàn)對數(shù)據(jù)庫的添加操作。最后此系統(tǒng)實(shí)現(xiàn)了群聊與私聊的功能,并能夠?qū)⒘奶煊涗浄诸惐4娴綌?shù)據(jù)庫中。關(guān)鍵詞:android,socket通信,線程同步,tcp/ip協(xié)議i嵌入式課程設(shè)計(jì)(論文) 目錄嵌入式課程設(shè)計(jì)(論文) 目錄目 錄中文摘要1 tcp/ip及socket簡介1 1.1 tcp/ip協(xié)議簡介1 1.2 socket套接字簡介12 系統(tǒng)總體架構(gòu)23 系統(tǒng)功能實(shí)現(xiàn)33.1 數(shù)據(jù)交互格式33.2 服務(wù)器功能實(shí)現(xiàn)4 3.2.1 startserver類4 3.2.2 serverthread類5 3.2.3 clientthread類6 3.2.4 broadcast類8 3.2.1

4、dodatabase類103.3 客戶端功能實(shí)現(xiàn)113.4 系統(tǒng)功能展示153.4.1客戶端功能展示153.4.2服務(wù)器端及數(shù)據(jù)庫展示16 4 系統(tǒng)存在的問題及改進(jìn)方法17 4.1 系統(tǒng)存在的問題174.2 系統(tǒng)改進(jìn)方法174 自我評價(jià)18ii參考文獻(xiàn)19嵌入式課程設(shè)計(jì)(論文) 1 tcp/ip及socket簡介1 tcp/ip及socket簡介 1.1 tcp/ip協(xié)議簡介tcp/ip是transm control protocol/internet protocol 的簡寫,又稱網(wǎng)絡(luò)通信協(xié)議,是internet最基本的協(xié)議。tcp/ip協(xié)議是“可靠的”、“面相連接”的網(wǎng)絡(luò)傳輸協(xié)議。tcp/

5、ip協(xié)議遵循的是一個(gè)抽象的分層模型,這個(gè)模型中所有的tcp/ip系列網(wǎng)絡(luò)協(xié)議都被歸納到四個(gè)抽象的“層”中。每一抽象層建立在低一層提供的服務(wù)上,并為高一層服務(wù)。tcp/ip參考模型從上到下分別包括網(wǎng)絡(luò)接口層、網(wǎng)絡(luò)互連層、傳輸層和應(yīng)用層四層。1.2 socket套接字簡介在網(wǎng)絡(luò)上的兩個(gè)程序通過一個(gè)雙向的通信鏈路實(shí)現(xiàn)數(shù)據(jù)交換,這個(gè)雙向鏈路的一段就被稱為一個(gè)socket,socket通常用來實(shí)現(xiàn)客戶端和服務(wù)器端的鏈接。socket是tcp/ip協(xié)議的一個(gè)十分流行的編程界面,一個(gè)socket有一個(gè)ip地址和一個(gè)端口號確定。在java環(huán)境中實(shí)現(xiàn)基于tcp/ip協(xié)議的網(wǎng)絡(luò)編程都需要采用socket機(jī)制。并且

6、與基于url的網(wǎng)絡(luò)編程socket編程提供更高的傳輸效率。socket通常采用c/s結(jié)構(gòu),使用socket進(jìn)行c/s程序設(shè)計(jì)的一般鏈接過程如下圖:圖1.1 socket編程連接一般過程- 19 -嵌入式課程設(shè)計(jì)(論文) 2 系統(tǒng)總體架構(gòu)2 系統(tǒng)總體架構(gòu)整個(gè)系統(tǒng)由客戶端和服務(wù)器端組成,其中客戶端位于android模擬器上,服務(wù)器端位于pc上。客戶端創(chuàng)建的socket與服務(wù)端的serversocket進(jìn)行交互來實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)交互。其中socket與serversocket交互過程如下:(1) 服務(wù)器端程序創(chuàng)建一個(gè)serversocket,然后調(diào)用accept()方法等待客戶連接(2) 客戶端創(chuàng)建一個(gè)

7、socket并請求與服務(wù)器端程序建立連接。(3) 服務(wù)器端程序接受客戶端的連接請求,并創(chuàng)建一個(gè)新的socket與該客戶端建立專線連接。(4) 建立了連接的客戶端及服務(wù)器端的兩個(gè)socket在一個(gè)有服務(wù)器端程序創(chuàng)建的單獨(dú)線程上對話,對話方式采用getinputstream()、getoutputstream()得到的輸入與輸出流進(jìn)行數(shù)據(jù)的讀取與輸出??蛻舳说膕ocket與服務(wù)器端的serversocket的通信如下圖:圖2.1 socket與serversocket通信圖(5) 服務(wù)器端開始等待新的連接請求,重復(fù)(2)(5)的過程。在客戶端程序?qū)崿F(xiàn)了界面的顯示以及與服務(wù)器端的數(shù)據(jù)交互。在服務(wù)器端

8、程序一共包含五個(gè)類,其名稱及功能如下表所示:startserver啟動服務(wù)器主線程serverthread,即啟動服務(wù)器serverthread服務(wù)器監(jiān)聽端口線程,負(fù)責(zé)創(chuàng)建serversocket以及監(jiān)聽是否有新客戶端連接,并記錄客戶端連接以及需要發(fā)送的消息clientthread維持服務(wù)器與單個(gè)客戶端的連接線程,負(fù)責(zé)接受客戶端發(fā)送來的消息broadcast服務(wù)器向客戶端發(fā)送廣播線程,負(fù)責(zé)向客戶端發(fā)送消息dodatabase連接數(shù)據(jù)庫,將消息拆解后按類型存放到數(shù)據(jù)庫chatdemo的messages表中表2.1 服務(wù)器端程序的四個(gè)類功能實(shí)現(xiàn)通信功能的流程圖如下:圖2.2 系統(tǒng)通信功能流程圖嵌入

9、式課程設(shè)計(jì)(論文) 3 系統(tǒng)功能實(shí)現(xiàn)3 系統(tǒng)功能實(shí)現(xiàn)3.1數(shù)據(jù)交互格式對于此聊天系統(tǒng),主要存在如下三類數(shù)據(jù):1、登陸2、傳遞消息3、退出這三類數(shù)據(jù)都是需要向服務(wù)器端發(fā)送的數(shù)據(jù),因?yàn)榱嗽诜?wù)器端處理的數(shù)據(jù)不被混淆,必須對他們的數(shù)據(jù)格式進(jìn)行規(guī)格化,此系統(tǒng)的數(shù)據(jù)規(guī)格如下圖:表3.1 消息格式圖消息種類: “l(fā)”登陸;“s”傳遞消息;“c”退出,目的地址: 要發(fā)往特定客戶端的手機(jī)號標(biāo) 識: 用來標(biāo)識不同種類的信息符號其中“$”發(fā)送的消息標(biāo)識;“#”客戶上下線標(biāo)識。源 地 址: 消息來源的客戶端手機(jī)號碼時(shí) 間: 獲取到的發(fā)送消息時(shí)的時(shí)間內(nèi) 容: 如果登陸則為“上線了”,如果退出則為“下線了”,如果是傳遞

10、消息則為想發(fā)送的內(nèi)容;其中對于登陸和退出消息,送往服務(wù)器端進(jìn)行拆分后將其目標(biāo)地址置空,對于傳遞消息,如果目標(biāo)地址和源地址相同則表示將該消息發(fā)送給所有的客戶端,反之,則只是發(fā)送到這兩個(gè)地址的客戶端中。3.2服務(wù)器端功能實(shí)現(xiàn)3.2.1 startserver類startserver線程是整個(gè)服務(wù)器的主線程,當(dāng)執(zhí)行這個(gè)工程文件時(shí)執(zhí)行這個(gè)類中的main函數(shù),在main函數(shù)中創(chuàng)建了一個(gè)實(shí)例化了一個(gè)serverthread線程命名為serverthread,并啟動該線程,代碼如下:public class startserver private static serverthread serverthre

11、ad;public static void main(string args) / todo auto-generated method stubserverthread = new serverthread();serverthread.start();3.2.2 serverthread類該類在構(gòu)造函數(shù)中實(shí)例化了兩個(gè)vector數(shù)組,分別用于存放clientthread線程和存放從客戶端發(fā)送來的消息,并命名為clients 和messages。此外還對serversocket進(jìn)行了初始化,然后啟動broadcast方法。代碼如下:public vector<clientthread&

12、gt; clients;public vector<object> messages;public serverthread()clients = new vector<clientthread>();messages= new vector<object>();try serversocket = new serversocket(port); catch (ioexception e) / todo auto-generated catch blocke.printstacktrace();try myipaddress = inetaddress.ge

13、tlocalhost(); catch (unknownhostexception e) / todo auto-generated catch blocke.printstacktrace();broadcast = new broadcast(this);broadcast.start();構(gòu)造方法執(zhí)行后,接著執(zhí)行該線程的run()方法。在run()函數(shù)中用了一個(gè)死循環(huán)實(shí)現(xiàn)不停的對客戶端的連接進(jìn)行監(jiān)聽,一旦監(jiān)聽到客戶端的連接請求,就獲得該客戶端的socket并將其封裝在clientthread線程中,然后啟動clientthread線程并將該線程壓入clients數(shù)組中以實(shí)現(xiàn)服務(wù)器與指定客

14、戶端或所有客服端發(fā)送數(shù)據(jù)。此外由于clients屬于臨界資源,同一時(shí)刻只能允許被一個(gè)線程操作,因此使用了線程同步方法synchronized(clients)。代碼如下:public void run()while(true)try socket socket = serversocket.accept();system.out.println(socket.getinetaddress().gethostaddress();clientthread clientthread = new clientthread(socket,this);clientthread.start();if(soc

15、ket!=null)synchronized(clients)clients.addelement(clientthread); catch (ioexception e) / todo auto-generated catch blocke.printstacktrace();3.2.3 clientthread類當(dāng)serverthread線程開啟了clientthread線程后,通過構(gòu)造函數(shù)獲得了客戶端的socket套接字,然后通過socket的getinputstream()方法和getoutputstream()方法獲取輸入輸出流。public clientthread(socket

16、socket,serverthread serverthread)this.clientsocket = socket;this.serverthread = serverthread;try in = new datainputstream(clientsocket.getinputstream();out = new dataoutputstream(clientsocket.getoutputstream(); catch (ioexception e) / todo auto-generated catch blocke.printstacktrace();然后執(zhí)行run()方法監(jiān)聽s

17、ocket是否有新的消息,然后根據(jù)消息的類別相應(yīng)處理后在控制臺上顯示出來,并把message的第14到25的子串(username)作為clientthread的唯一標(biāo)識id,此標(biāo)識可以用來實(shí)現(xiàn)從一個(gè)客戶端向另一指定客戶端發(fā)送數(shù)據(jù)。并利用domsg()方法將message拆分后存放到數(shù)據(jù)庫中,同時(shí)將message壓入到messages消息隊(duì)列中。代碼如下:public void run()while(true)try string message = in.readutf();synchronized(serverthread.messages)if(message !=null)domsg(

18、message);id = message.substring(14, 25);serverthread.messages.addelement(message);if(message.subsequence(0, 1).equals("s")if(message.substring(1,12).equals(message.substring(14,25)system.out.println(message.substring(1,12) + message.substring(24);elsesystem.out.println("$"+messag

19、e.substring(14,25)+" 對 "+message.substring(1,12)+message.substring(25);elsesystem.out.println(message.substring(12); catch (ioexception e) / todo auto-generated catch blocke.printstacktrace();break;private void domsg(string message) / todo auto-generated method stubcatgory = message.substr

20、ing(0,1);orgid = message.substring(14,25);time = message.substring(26,34);if(catgory.equals("s")goalid = message.substring(1,12);content =message.substring(36);elsegoalid = ""content =message.substring(34);try dodb.addmsg(time, catgory, orgid, goalid, content); catch (exception e

21、) / todo auto-generated catch blocke.printstacktrace();3.2.4 broadcast類通過serverthread線程調(diào)用該類后,serverthread類通過broadcast構(gòu)造函數(shù)傳給serverthread實(shí)例,然后執(zhí)行該線程的run()方法,沒循環(huán)一次線程休眠200ms,然后取出messages中尚未發(fā)送出的消息,將消息按其格式拆分后根據(jù)其意圖送往各個(gè)客戶端或是指定客戶端,是實(shí)現(xiàn)群聊個(gè)私聊的功能。同樣,消息數(shù)組是臨界資源,所以,用到了synchronized(serverthread.messages)方法,判斷該消息為下線功能

22、,則將根據(jù)id刪除vector中的clientthread線程。源代碼如下:public void run()while(true)try thread.sleep(200); catch (interruptedexception e) / todo auto-generated catch blocke.printstacktrace();synchronized(serverthread.messages)if(serverthread.messages.isempty()continue;/獲取消息隊(duì)列隊(duì)首消息str = (string)this.serverthread.messag

23、es.firstelement();synchronized(serverthread.clients)system.out.println(serverthread.clients.size();for(int i=0;i<serverthread.clients.size();i+)/獲取該客戶端線程clientthread =(clientthread)serverthread.clients.elementat(i);try clientthread.out.writeutf(str); catch (ioexception e) / todo auto-generated ca

24、tch blocke.printstacktrace();/從消息隊(duì)列中刪除該消息this.serverthread.messages.remove(str);3.2.5 dodatabase類該類有兩個(gè)方法addmsg()和getconnection()方法,其中g(shù)etconnection()方法用于獲取數(shù)據(jù)庫chatdemo的連接句柄。addmsg()方法用于對chatdemo中的表messages進(jìn)行寫操作。實(shí)現(xiàn)代碼如下:public class dodatabase public void addmsg(string time, string catgory, string orgid

25、, string goalid, string content)throws exception /打開連接connection conn = getconnection();/ 執(zhí)行操作preparedstatement pst = conn.preparestatement("insert into messages values(?,?,?,?,?)");pst.setstring(1, time); /時(shí)間pst.setstring(2, catgory);/消息種類pst.setstring(3, orgid);/源地址pst.setstring(4, goali

26、d);/目的地址pst.setstring(5, content);/內(nèi)容pst.execute();/ 關(guān)閉數(shù)據(jù)庫conn.close();private connection getconnection() throws classnotfoundexception,sqlexception class.forname("net.sourceforge.jtds.jdbc.driver");connection conn = drivermanager.getconnection("jdbc:jtds:sqlserver:/localhost:1433/cha

27、tdemo", "sa", "");return conn;3.3客戶端功能實(shí)現(xiàn)圖3.1 客戶端界面其源代碼如下:public class chatclientactivity extends activity implements runnableprivate edittext usernameedit,ipedit,historyedit,messageedit;private button loginbutton,leavebutton,sendbutton;private string username ,ip,chat_txt,ch

28、at_in;public static final int port = 8521;/端口號public datainputstream in=null;public dataoutputstream out=null;public socket socket;public thread thread;public boolean flag = false; /標(biāo)識是否登陸,true為已登錄,false為未登錄 override public void oncreate(bundle savedinstancestate) super.oncreate(savedinstancestate);

29、 setcontentview(r.layout.main); usernameedit = (edittext)findviewbyid(r.id.username); ipedit = (edittext)findviewbyid(r.id.ip); historyedit = (edittext)findviewbyid(r.id.history); messageedit = (edittext)findviewbyid(r.id.message); loginbutton = (button)findviewbyid(r.id.loginbutton); leavebutton =

30、(button)findviewbyid(r.id.leave); sendbutton = (button)findviewbyid(r.id.sendbutton); loginbutton.setonclicklistener(listener); leavebutton.setonclicklistener(listener); sendbutton.setonclicklistener(listener); view.onclicklistener listener = new view.onclicklistener() overridepublic void onclick(vi

31、ew v) / todo auto-generated method stubswitch(v.getid()case r.id.loginbutton:/登陸if(flag=true)toast.maketext(chatclientactivity.this, "已經(jīng)登陸過了", 3000).show();return;username = usernameedit.gettext().tostring();ip = ipedit.gettext().tostring();if(username!="" && username!=nu

32、ll && ip != null)/目的地址和源地址不能為空;try socket = new socket(ip,port); /實(shí)例化socket/獲取輸入輸出流in = new datainputstream(socket.getinputstream();out = new dataoutputstream(socket.getoutputstream();date now = new date(system.currenttimemillis(); /獲取系統(tǒng)時(shí)間simpledateformat format = new simpledateformat("

33、hh:mm:ss");string nowstr = format.format(now);out.writeutf("$"+username+" " +nowstr+"上線了"); catch (unknownhostexception e) / todo auto-generated catch blocke.printstacktrace(); catch (ioexception e) / todo auto-generated catch blocke.printstacktrace();thread = new

34、thread(chatclientactivity.this);thread.start();flag = true;break;case r.id.sendbutton: /發(fā)送消息if(flag = false)toast.maketext(chatclientactivity.this, "沒有登陸,請登陸", 3000).show();return;chat_txt = messageedit.gettext().tostring();if(chat_txt !=null)date now = new date(system.currenttimemillis();

35、 /獲取當(dāng)前時(shí)間simpledateformat format = new simpledateformat("hh:mm:ss");string nowstr = format.format(now);try out.writeutf("_"+username+" "+nowstr+"說n"+chat_txt); catch (ioexception e) / todo auto-generated catch blocke.printstacktrace();elsetry out.writeutf("

36、;請說話"); catch (ioexception e) / todo auto-generated catch blocke.printstacktrace();break;case r.id.leave: /退出if(flag = false)toast.maketext(chatclientactivity.this, "沒有登陸,請登陸", 3000).show();return;try out.writeutf("#"+username+"下線了!");out.close();in.close();socket.

37、close(); catch (ioexception e) / todo auto-generated catch blocke.printstacktrace();flag = false;toast.maketext(chatclientactivity.this, "已經(jīng)退出!", 3000).show();break;overridepublic void run() /服務(wù)端反饋的消息/ todo auto-generated method stubwhile(true)try chat_in = in.readutf();chat_in +="n&q

38、uot;mhandler.sendmessage(mhandler.obtainmessage(); /發(fā)到主線程的消息隊(duì)列中 catch (ioexception e) / todo auto-generated catch blocke.printstacktrace();handler mhandler = new handler()public void handlemessage(message msg)historyedit.append(chat_in); /在historyedit文本框中追加消息super.handlemessage(msg);3.4系統(tǒng)功能展示3.2.1 客

39、戶端功能展示圖3.2 客戶端5554發(fā)送接收消息界面 圖3.3 客戶端5556發(fā)送接收消息界面圖3.4 客戶端5558發(fā)送接收消息界面3.2.1 服務(wù)器端及數(shù)據(jù)庫展示圖3.5 服務(wù)器控制臺顯示 圖3.6 數(shù)據(jù)庫存儲顯式嵌入式課程設(shè)計(jì)(論文) 4 系統(tǒng)存在的問題及改進(jìn)方法4 系統(tǒng)存在問題及改進(jìn)方法4.1系統(tǒng)存在的問題此系統(tǒng)實(shí)現(xiàn)了android系統(tǒng)聊天室的群聊和私聊功能以及實(shí)現(xiàn)了在服務(wù)器端將接收到的消息存儲到,但是由于時(shí)間限制此系統(tǒng)基本實(shí)現(xiàn)了android系統(tǒng)的聊天室的實(shí)現(xiàn)群發(fā)功能,但是由于時(shí)間較緊,還有一些沒有實(shí)現(xiàn)的功能。首先在安全性上考慮不周,登陸時(shí)只需要輸入用戶名就能夠進(jìn)入系統(tǒng),而且沒有檢測多個(gè)模擬器上是否有同名的情況。其次,對很多可能出現(xiàn)異常的情況沒有處理。再次,設(shè)計(jì)上還不夠嚴(yán)謹(jǐn),在客戶端與服務(wù)器端進(jìn)行數(shù)據(jù)通信時(shí)有很多數(shù)據(jù)交互,此系統(tǒng)只實(shí)現(xiàn)了在客戶端對發(fā)送的消息進(jìn)行了記錄,但只實(shí)現(xiàn)了數(shù)據(jù)庫的寫操作。在客戶端本地沒有實(shí)現(xiàn)數(shù)據(jù)存儲機(jī)制以便日后需要,比如:用戶名,密碼等。最后,android客戶端界面設(shè)計(jì)不足,比如:當(dāng)歷史記錄edittext中存放了太多內(nèi)容時(shí)需要

溫馨提示

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

評論

0/150

提交評論