《綜合課程設(shè)計》設(shè)計報告基于Socket的即時通訊系統(tǒng)_第1頁
《綜合課程設(shè)計》設(shè)計報告基于Socket的即時通訊系統(tǒng)_第2頁
《綜合課程設(shè)計》設(shè)計報告基于Socket的即時通訊系統(tǒng)_第3頁
《綜合課程設(shè)計》設(shè)計報告基于Socket的即時通訊系統(tǒng)_第4頁
《綜合課程設(shè)計》設(shè)計報告基于Socket的即時通訊系統(tǒng)_第5頁
已閱讀5頁,還剩14頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、評閱教師評語:課程設(shè)計成績考勤成績實做成績報告成績總評成績指導(dǎo)教師簽名:綜合課程設(shè)計設(shè) 計 報 告論文題目: 基于socket的即時通訊系統(tǒng) 學(xué)院(系): 電子信息與自動化學(xué)院 班 級: 721 學(xué)生姓名: 學(xué)號 指導(dǎo)教師: 時間: 2011 年 6月 7日 到 2011 年 6 月 17日一、 設(shè)計目的通過綜合課程設(shè)計,使學(xué)生能夠運用數(shù)字信號處理、信號與系統(tǒng)、通信原理、面向?qū)ο蟮某绦蛟O(shè)計、計算機通信網(wǎng)、通信協(xié)議開發(fā)及應(yīng)用等課程的知識來設(shè)計一個基于socket的即時通訊系統(tǒng),培養(yǎng)學(xué)生的動手能力以及分析問題、解決問題的能力。二、 設(shè)計內(nèi)容一個基于socket的即時通訊系統(tǒng)的多人聊天軟件三、 設(shè)計

2、要求(一)基本要求1 熟練掌握面向?qū)ο蟮某绦蛟O(shè)計方法;2 實現(xiàn)點對點通訊,能進行文字對話傳輸,包括客戶端與服務(wù)器端;3 能對系統(tǒng)參數(shù)進行配置。(二)提高要求1、實現(xiàn)文件、圖片傳輸;2、語音對話(兩人及兩人以上);3、友好的對話界面。四、 設(shè)計原理1 tcp/ip簡介 tcp/ip的歷史要追溯到70年代中期,當(dāng)時arpa為了實現(xiàn)異種網(wǎng)之間的互連(interconnection)與互通(intercommunication),大力資助網(wǎng)間網(wǎng)技術(shù)的研究和開發(fā),于1977年到1979年推出目前形式的tcp/ip體系結(jié)構(gòu)和協(xié)議規(guī)范.到今天,tcp/ip技術(shù)以及internet網(wǎng)間網(wǎng)已經(jīng)為廣大計算機工作者

3、,機算機廠商和機算機用戶所接受.據(jù)統(tǒng)計,到1990年,internet以包含遍布歐美的五千個活動網(wǎng)絡(luò),超過三十萬臺機算機.作為一種事實上的工標準,tcp/ip技術(shù)方興未艾.2 tcp/ip的網(wǎng)絡(luò)分層結(jié)構(gòu) 對tcp/ip協(xié)議來說,tcp提供傳輸層服務(wù),ip提供網(wǎng)絡(luò)層服務(wù).tcp/ip協(xié)議組(或internet協(xié)議組)的分層結(jié)構(gòu)及其與osi模型的對應(yīng)關(guān)系如圖4所示.圖中有關(guān)協(xié)議的名稱及其基本含義如下: (1) tcp. 為傳輸控制協(xié)議(transmission control protocol).它是提供給用戶進程的一個可靠的全雙工字節(jié)流的面向連接的協(xié)議.大多數(shù)internet應(yīng)用程序使用tcp.

4、因為tcp使用ip,所以整個internet協(xié)議組也常稱為tcp/ip協(xié)議組. (2) udp. 為用戶數(shù)據(jù)報協(xié)議 (user datagram protocol). (3) icmp. 為網(wǎng)間報文控制協(xié)議 (internet control message protocol). (4) ip. 網(wǎng)間協(xié)議 (internet protocol). ip協(xié)議是為tcp,udp和icmp提供分組發(fā)送服務(wù)協(xié)議. (5) arp. 地址轉(zhuǎn)換協(xié)議. (6) rarp. 反向地址轉(zhuǎn)換協(xié)議.3 socket編程界面 (1) socket 原理 socket編程界面由4bsd unix首先提出,目的是解決網(wǎng)間

5、網(wǎng)進程通信問題.socket接口為進程間通信提供了一種新的手段,它不但能用于同一機器中的進程之間的通信,而且支持網(wǎng)絡(luò)通信功能.socket具有類型,反應(yīng)了對用戶透明的通信特性. 一個完整的socket連接用一個相關(guān)描述: 協(xié)議,本地地址,本地端口,遠地地址,遠地端口 socket 是面向客戶-服務(wù)器模型而設(shè)計的,針對客戶和服務(wù)器程序提供不同的socket系統(tǒng)調(diào)用. (2) socket系統(tǒng)調(diào)用 不管socket內(nèi)部機制如何,它提供給應(yīng)用程序員的最終界面是一組系統(tǒng)功能調(diào)用.下面,我們一一給出重要的socket系統(tǒng)調(diào)用. 1. 創(chuàng)建 socket - socket() 調(diào)用格式如下: sockid

6、 = socket (af,type,protocol) af : 地址族,指本socket所用地址類型. type : 類型,指創(chuàng)建socket的應(yīng)用程序所希望的通信服務(wù)器類型. protocol : 協(xié)議,指本socket請求的協(xié)議. 2. 指定本地地址 - bind()調(diào)用 bind()將本地socket地址與所創(chuàng)建的socket聯(lián)系起來,即將本socket地址賦予socket,以指定本地半相關(guān).bind()的作用相當(dāng)于給socket命名,調(diào)用格式為: bind (sockid,localaddr,addrlen) sockid : socket號. localaddr : 本地sock

7、et地址. addrlen : 地址長度. 3. 建立socket連接 - connect () 與 accept ()調(diào)用 這兩個系統(tǒng)調(diào)用用于完成整個相關(guān)的建立.其中connect用于建立連接 .調(diào)用格為: connect (sockid,destaddr,addrlen) destaddr : 指向?qū)Ψ絪ocket地址(信宿地址)結(jié)構(gòu)的指針. accept : 用于面向連接的服務(wù)器,其調(diào)用格式為: newsock = accept (sockid,clientaddr,paddrlen) clientaddr : 指向客戶socket地址指針. paddrlen : 客戶socket地址長

8、度. 4. listen() 調(diào)用 此調(diào)用用于面向連接服務(wù)器,表明它愿意接收連接,listen()在accept()之前調(diào)用,格式為: listen (sockid,quelen) quelen : 請求隊列長度. 5. 發(fā)送數(shù)據(jù) - write(),writev(),send()與sendto(),sendmsg() 用于socket數(shù)據(jù)發(fā)送的系統(tǒng)調(diào)用一共有五個,其中三個,write(),writev()和send()用于面向連接傳輸,其余兩個用于無連接傳輸.面向連接的調(diào)用可以不指定信宿地址,而無連接的調(diào)用必須指定.假如無連接socket的雙方均調(diào)用過connect(),可以認為是建立有連接

9、的socket,也可以面向連接調(diào)用發(fā)送數(shù)據(jù). 三個面向連接調(diào)用三者的格式大致相同: write (sockid,buff,bufflen) : 緩沖發(fā)送 writev (sockid,iovector,vectorlen) : 集中發(fā)送 send (sockid,buff,bufflen,flags) : 可控緩沖發(fā)送 其中buff指向發(fā)送緩沖區(qū)的指針,bufflen是發(fā)送緩沖區(qū)大小. 用于無連接數(shù)據(jù)發(fā)送的調(diào)用有兩個: sendto (sockid,buff,bufflen,flags,dsadd,addrlen) sendmsg (sockid,message,flags):可控集中無連接發(fā)

10、送. 6. 接收數(shù)據(jù) - read(),readv(),recv()與recvfrom(),recvmsg() 接收數(shù)據(jù)與發(fā)送數(shù)據(jù)系統(tǒng)調(diào)用是一一對應(yīng)的,兩者參數(shù)的最大區(qū)別是,前者buffer是一個指針,其所指單元初值為欲讀數(shù)據(jù)長度,調(diào)用后的值是實際讀出的值.4 客戶-服務(wù)器模型的socket實現(xiàn)框架 1)客戶-服務(wù)器模型時序圖 下圖是面向連接客戶-服務(wù)器模型的典型時序圖 服務(wù)器 客戶 socket() socket() bind() bind() listen() accept() 等待客戶連接請求 阻塞 connect() read() write() 2)服務(wù)器socket地址的確定在客戶

11、-服務(wù)器模型中,所有的作用者都是客戶首先發(fā)起的(如連接請求,服務(wù)請求等),因此客戶必須要知道服務(wù)器socket地址,另外,客戶調(diào)用服務(wù)器之前,可以在命令行中給出服務(wù)器所在主機的域名,根據(jù)域名可以獲得服務(wù)器主機的地址,系統(tǒng)調(diào)用為:hp=gethostbyname(host).其中host可以是服務(wù)器主機域名,返回hp是一個指向主機地址結(jié)構(gòu)的指針。五、 軟件設(shè)計(附程序流程圖、源程序清單)1. 程序流程圖2.源程序清單void cchatroomdlg:dlgallinit()checkradiobutton(idc_radio_client, idc_radio_server, idc_radi

12、o_client);setdlgitemtext(idc_ip_addr, _t(); / 初始化ip地址為本機地址。setdlgitemtext(idc_connect_port, _t(5566); / 初始化端口。setdlgitemtext(idc_listen_port, _t(5566);enablewindow(idc_stop_client, false);enablewindow(idc_listen_port, false);enablewindow(idc_stop_server, false);enablewindow(idc_start_server

13、, false);enablewindow(idc_static_listen_port, false); / 初始化按鍵啟用or禁用。enablewindow(idc_sendmsg, false);bool cchatroomdlg:enablewindow(uint uid, bool benable)return getdlgitem(uid)-enablewindow(benable);void cchatroomdlg:extenddiaog(bool bshow)static crect m_dlgrectlarge(0, 0, 0, 0);static crect m_dlgr

14、ectsmall(0, 0, 0, 0);static crect m_grouprectlarge(0, 0, 0, 0);static crect m_grouprectsmall(0, 0, 0, 0); / 設(shè)置 窗口大小 if ( m_dlgrectlarge.isrectnull() ) getwindowrect(&m_dlgrectlarge);m_dlgrectsmall = m_dlgrectlarge;m_dlgrectsmall.right -= 220;:getwindowrect(getdlgitem(idc_frame)-getsafehwnd(), &m_gro

15、uprectlarge);m_grouprectsmall = m_grouprectlarge;m_grouprectsmall.right -= 220; / 設(shè)置 窗口 伸縮大小范圍if ( bshow ) bshowall = true;setwindowpos(null, 0, 0, m_dlgrectlarge.width(), m_dlgrectlarge.height(), swp_nozorder | swp_nomove);:setwindowpos(getdlgitem(idc_frame)-getsafehwnd(), null, 0, 0, m_grouprectla

16、rge.width(), m_grouprectlarge.height(), swp_nozorder | swp_nomove);elsebshowall = false;setwindowpos(null, 0, 0, m_dlgrectsmall.width(), m_dlgrectsmall.height(), swp_nozorder | swp_nomove);:setwindowpos(getdlgitem(idc_frame)-getsafehwnd(), null, 0, 0, m_grouprectsmall.width(), m_grouprectsmall.heigh

17、t(), swp_nozorder | swp_nomove);void cchatroomdlg:onbnclickednetset()if ( bshowall ) extenddiaog(false);elseextenddiaog(true); / 設(shè)置按鍵“網(wǎng)絡(luò)設(shè)置”的作用void cchatroomdlg:onbnclickedstartserver()m_hlistenthread = createthread(null, 0, listenthreadfunc, this, 0, null);void cchatroomdlg:showmsg(cstring strmsg)m_

18、msgedit.setsel(-1, -1);m_msgedit.replacesel(strmsg+_t(rn);void cchatroomdlg:removeclientfromarray(cclientitem in_item)for( int idx = 0; idx ) + strmsg;showmsg(strmsg);sendclientsmsg(strmsg);else if (m_bisserver = false) cstring strtmp = _t(張智超的客戶端:) + strmsg;showmsg(strtmp);int isend = send(m_connec

19、tsock, (char *)strmsg.getbuffer(), strmsg.getlength()*sizeof(tchar), 0);strmsg.releasebuffer();elseafxmessagebox(_t(請您先進入聊天室!);setdlgitemtext(idc_input_msg, _t(); / socket 基本應(yīng)用void cchatroomdlg:onbnclickedstartclient()m_hconnectthred = createthread(null, 0, connectthreadfunc, this, 0, null);void cch

20、atroomdlg:sendclientsmsg(cstring strmsg, cclientitem *pnotsend)tchar szbufmax_buf_size = 0;_tcscpy_s(szbuf, max_buf_size, strmsg);for( int_ptr idx = 0; idx m_socket != m_clientarray.getat(idx).m_socket | pnotsend-hthread != m_clientarray.getat(idx).hthread |pnotsend-m_strip != m_clientarray.getat(id

21、x).m_strip) send(m_clientarray.getat(idx).m_socket, (char *)szbuf, _tcslen(szbuf)*sizeof(tchar), 0);void cchatroomdlg:onenchangeinputmsg()cstring strmsg;getdlgitemtext(idc_input_msg, strmsg);if ( strmsg.isempty() ) enablewindow(idc_sendmsg, false);elseenablewindow(idc_sendmsg);void cchatroomdlg:stop

22、client()bshutdown = true;dword dwret = waitforsingleobject(m_hconnectthred, 1000);if ( dwret != wait_object_0 ) terminatethread(m_hconnectthred, -1);closesocket(m_connectsock);m_hconnectthred = null;m_connectsock = invalid_socket;m_bisserver = -1;bshutdown = false;void cchatroomdlg:stopserver()uint

23、ncount = m_clientarray.getcount();handle *m_phandles = new handlencount+1;m_phandles0 = m_hlistenthread;for( int idx = 0; idx ncount; idx+ ) m_phandlesidx+1 = m_clientarray.getat(idx).hthread;bshutdown = true;dword dwret = waitformultipleobjects(ncount+1, m_phandles, true, 1000);if ( dwret != wait_o

24、bject_0 ) for( int_ptr i = 0; i getwindowrect(&mrect);pt = mrect.bottomright();pt.y = mrect.top+10;mmenu.loadmenu(idr_menu1);pmenu = mmenu.getsubmenu(0);pmenu-trackpopupmenu(tpm_leftalign | tpm_rightbutton, pt.x, pt.y, this);bool cchatroomdlg:traymyicon(bool badd)bool bret = false;notifyicondata tnd

25、;tnd.cbsize = sizeof(notifyicondata);tnd.hwnd = getsafehwnd();tnd.uid = idr_mainframe;if ( badd = true ) tnd.uflags = nif_message | nif_icon | nif_tip;tnd.ucallbackmessage = wm_trayicon_msg;tnd.hicon = loadicon(afxgetinstancehandle(), makeintresource(idr_mainframe);_tcscpy_s(tnd.sztip, sizeof(tnd.sz

26、tip), _t(聊天室v1.0);showwindow(sw_minimize);showwindow(sw_hide);bret = shell_notifyicon(nim_add, &tnd);elseshowwindow(sw_showna);setforegroundwindow();bret = shell_notifyicon(nim_delete, &tnd);return bret;void cchatroomdlg:onmenutrayinco()traymyicon();lresult cchatroomdlg:ontraycallbackmsg(wparam wpar

27、am, lparam lparam)switch(lparam)case wm_rbuttonup:cmenu mmenu, *pmenu = null;cpoint pt;mmenu.loadmenu(idr_menu2);pmenu = mmenu.getsubmenu(0);getcursorpos(&pt);setforegroundwindow();pmenu-trackpopupmenu(tpm_leftalign | tpm_rightbutton, pt.x, pt.y, this);break;case wm_lbuttondblclk:showwindow(sw_resto

28、re);setforegroundwindow();traymyicon(false);break; 3. 附錄:課程設(shè)計中要用到的winsock函數(shù)wsastartup初始化socket庫wsacleanup結(jié)束socket庫的使用socket為所要進行的網(wǎng)絡(luò)通信建立標識符connect連接到遠程主機closesocket結(jié)束通信,關(guān)閉標識符bind將ip地址、tcp端口號與套接字標識符綁定listen將接受套接字置于被動模式,將服務(wù)器置于偵聽狀態(tài),并指定允許的連接數(shù)accept接受下一個呼入的連接recv接收傳入的tcp數(shù)據(jù)recvfrom接收傳入的udp數(shù)據(jù)select在指定的套接字集準

29、備好接收數(shù)據(jù)前一直等待send發(fā)送tcp數(shù)據(jù)sendto發(fā)送udp數(shù)據(jù)shutdown釋放tcp連接getpeername從套接字中獲取對等方的端口地址setsocketopt獲取當(dāng)前套接字的可變選項gethostbynameinet_addr把域名轉(zhuǎn)換成網(wǎng)絡(luò)ip地址把用點分十進制表示的ip地址轉(zhuǎn)換成網(wǎng)絡(luò)ip地址getservbynamegetprotobyname獲得服務(wù)器的端口號把tcp、udp轉(zhuǎn)換成相應(yīng)的服務(wù)號碼(interger)六、 調(diào)試過程測試的目的是為了發(fā)現(xiàn)功能是否達到,或者是否有更多的缺陷。當(dāng)兩個客戶端在建立連接時,出現(xiàn)過程序假死異常。分析代碼發(fā)現(xiàn),線程調(diào)度出錯,接收消息線程t

30、h還未創(chuàng)建和啟動,監(jiān)聽線程wait已經(jīng)被銷毀了。修改代碼,給出兩種解決辦法:(1)在th線程的執(zhí)行方法中,將wait線程銷毀;在th線程銷毀前,重新開啟wait線程。(2)wait線程不銷毀。設(shè)置一bool類型變量isconnected,當(dāng)已經(jīng)建立連接后,isconnected=true,若再有其他的連接請求到達,自動將其他連接請求拒絕。連接斷開后,重置isconnected=false,將處理移交給用戶。我采用了第一種方法,調(diào)試之后,問題解決。在程序退出時,常常發(fā)生錯誤,異常退出,造成表面上看程序已結(jié)束,但卻仍然駐留在內(nèi)存中的現(xiàn)象。經(jīng)過反復(fù)分析代碼,最終確定問題出在程序退出處理流程上,通過修

31、改和調(diào)試,問題解決。軟件圖示七、 實驗結(jié)果分析整個開發(fā)過程中,共歷經(jīng)多次相互斷開、連接測試,聊天模塊終于可以正常運行。借助在文本聊天模塊開發(fā)過程中積累的經(jīng)驗,較順利的完成了文件傳輸模塊的開發(fā)。通過在總集成后的程序的各個流程中添加消息提示框顯示程序內(nèi)部數(shù)據(jù)、對象的狀態(tài),并插入斷點進行單步跟蹤發(fā)現(xiàn)各模塊工作正常,數(shù)據(jù)也未發(fā)生異?,F(xiàn)象。(1)程序啟動之后就能看到當(dāng)前哪些機器在線,哪些可以與之進行對等通信。(2)一旦有某個網(wǎng)內(nèi)的機器上線了,要有即時通知,并能及時更新用戶界面中的用戶列表。(3)當(dāng)雙擊某個列表項的時候,要彈出聊天對話框,可以在其中編輯要發(fā)送的聊天信息,并進行發(fā)送。(4)聊天界面要人性化,下面是發(fā)送框,上面有已有聊天記錄,并借助滾動條看到當(dāng)次所有的聊天記錄。(5)當(dāng)有遠程用戶向本機發(fā)送文件的時候,要彈出一個消息提示框,提示本機用戶,可以選擇接收或者拒絕。(6)

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論