通信工程專業(yè)實習(xí)報告-2_第1頁
通信工程專業(yè)實習(xí)報告-2_第2頁
通信工程專業(yè)實習(xí)報告-2_第3頁
通信工程專業(yè)實習(xí)報告-2_第4頁
通信工程專業(yè)實習(xí)報告-2_第5頁
已閱讀5頁,還剩14頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

PAGE21目錄1前言………………………71.1實習(xí)單位簡介………………………71.2實習(xí)目的……………72實習(xí)內(nèi)容…………………83實習(xí)總結(jié)…………………273.1實習(xí)中遇到的問題…………………273.2實習(xí)收獲……………273.3實習(xí)建議……………283.4實習(xí)總結(jié)……………281前言1.1實習(xí)單位簡介1.2實習(xí)目的(1)通過實習(xí)使學(xué)生對所要設(shè)計的課題有一個初步的了解,獲得基本的感性認識,加深對課題的認識,學(xué)會理論聯(lián)系實際,擴大知識面,引發(fā)設(shè)計思路,對設(shè)計任務(wù)有更明確更深刻的理解;(2)通過撰寫實習(xí)報告和課題討論,使學(xué)生學(xué)會綜合應(yīng)用所學(xué)知識,提高應(yīng)用專業(yè)知識的能力,并為后續(xù)的畢業(yè)論文和畢業(yè)設(shè)計做好鋪墊和準備;(3)通過實習(xí)能夠開闊學(xué)生的視野,培養(yǎng)學(xué)生分析問題、解決問題的能力,進一步了解專業(yè)發(fā)展現(xiàn)狀和前景,為以后的工作方向有更好的定位。2實習(xí)內(nèi)容2.1文件操作2.1.1UNIX哲學(xué)之一:一切皆為文件Linux文件種類:1.普通文件2.目錄文件3.鏈接文件4.設(shè)備文件2.1.2關(guān)于文件描述符文件描述符是一個非負整數(shù),是一個索引值0STDIN_FILENO1STDOUT_FILENO2STDERR_FILENO包含在<unistd.h>文件描述符的范圍是0~OPEN_MAXLinux下OPEN_MAX為10485762.1.3不帶緩沖的文件I/O操作這次項目中將要用到的文件操作openclosereadwritelseek注:這些函數(shù)是ANSIC的組成部分,但是是POSIX的組成部分2.1.4關(guān)于出錯處理由于對文件的操作由于某種原因,比如文件打開失敗、文件讀、寫失敗,這些出錯會導(dǎo)致程序執(zhí)行失敗解決辦法:加上出錯處理,可以在出錯時很明了的發(fā)現(xiàn)錯誤出在哪里常用函數(shù):#include<errno.h>#include<stdio.h>voidperror(constchar*s);2.1.5不帶緩沖的文件操作函數(shù)open#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>Intopen(constchar*pathname,intflags);Intopen(constchar*pathname,intflags,mode_tmode);返回值:成功返回新分配的文件描述符,出錯返回-1并謳置errno2.1.6參數(shù)的含義pathname是要打開或創(chuàng)建的文件的名字。oflag參數(shù)可用于說明此函數(shù)的多個選擇項。mode對于open函數(shù)而言,僅當創(chuàng)建新文件時才使用第三個參數(shù)。以下三個常數(shù)中必須指定一個,且僅允講指定一個(這些常數(shù)定義在<fcntl.h>頭文件中):O_RDONLY只讀打開。O_WRONLY只寫打開。O_RDWR讀、寫打開。2.1.7可選以下可選項可以同時指定0個或多個,和必選項按位或來作為flags參數(shù)。O_APPEND每次寫時都加到文件的尾端。O_CREAT若此文件丌存在則創(chuàng)建它。使用此選擇項時,需同時說明第三個參數(shù)mode,用其說明該新文件的存取講可權(quán)位。O_EXCL如果同時指定了O_CREAT,而文件已經(jīng)存在,則出錯。這可測試一個文件是否存在,如果不存在則創(chuàng)建此文件成為一個原子操作。O_TRUNC如果此文件存在,而且為只讀或只寫成功打開,則將其長度截短為0。2.1.8第三個參數(shù)第三個參數(shù)mode指定文件權(quán)限,可以用八進制數(shù)表示,比如0644表示-rw-r--r--2.1.9close可用close函數(shù)關(guān)閉一個打開文件:#include<unistd.h>Intclose(intfiledes);返回:若成功為0,若出錯為-1當一個進程終止時,它所有的打開文件都由內(nèi)核自動關(guān)閉。2.1.10read用read函數(shù)從打開文件中讀數(shù)據(jù)#include<unistd.h>ssize_tread(intfeledes,void*buff,size_tnbytes);返回:讀到的字節(jié)數(shù),若已到文件尾為0,若出錯為-1。如read成功,則返回讀到的字節(jié)數(shù)。如已到達文件的尾端,則返回0。2.1.11write用write函數(shù)向打開文件寫數(shù)據(jù)。#include<unistd.h>ssize_twrite(intfiledes,constvoid*buff,size_tnbytes);返回:若成功為已寫的字節(jié)數(shù),若出錯為-1。其返回值通常不參數(shù)nbytes的值不同,否則表示出錯。write出錯的一個常見原因是:磁盤已寫滿,或者超過了對一個給定進程的文件長度限制。2.1.12lseek#include<sys/types.h>#include<unistd.h>off_tlseek(intfilesdes,off_toffset,intwhence);返回:若成功為新的文件位移,若出錯為-1。對參數(shù)offset的解釋不參數(shù)whence的值有關(guān)。若whence是SEEK_SET,則將該文件的位移量設(shè)置為距文件開始處offset個字節(jié)。若whence是SEEK_CUR,則將該文件的位移量設(shè)置為其當前值加offset,offset可為正或負。若whence是SEEK_END,則將該文件的位移量設(shè)置為文件長度加offset,offset可為正或負。2.1.13標準I/O操作標準i/o庫及其頭文件stdio.h為底層I/O系統(tǒng)調(diào)用提供了一個通用的接口,這個庫已經(jīng)成為ANSI標準C的一部分在啟動程序時,有三個文件流是自動打開的,他們是stdin,stdout,stderr這三個文件分別代表著標準輸入、標準輸出、標準錯誤輸出,與底層文件描述符0、1、2對應(yīng)標準I/O庫提供了大量的復(fù)雜函數(shù)2.1.14fopen函數(shù)函數(shù)原型#include<stdio.h>FILE*fopen(constchar*filename,constchar*mode)返回值:成功返回一個非空的FILE*指針,失敗時返回NULL參數(shù):mode可以是以下字符串中的一個(注意是字符串不是字符)2.1.15fopen“r”:只讀,文件必須已存在“w”:只寫,如果文件不存在則創(chuàng)建,如果文件已存在則把文件長度截斷(Truncate)為0字節(jié)再重新寫,也就是替換掉原來的的文件內(nèi)容“a”:只能在文件末尾追加數(shù)據(jù),如果文件不存在則創(chuàng)建“r+”:允許讀和寫,文件必須已存在“w+”:允許讀和寫,如果文件不存在則創(chuàng)建,如果文件已存在則把文件長度截斷為0字節(jié)再重新寫“a+”:允許讀和追加數(shù)據(jù),如果文件不存在則創(chuàng)建2.1.16fcloseIntfclose(FILE*fp);返回值:成功返回0,出錯返回EOF并設(shè)置errno2.1.17fread/fwrite原型:#include<stdio.h>size_tfread/fwrite(void*ptr,size_tsize,size_tnmemb,FILE*stream)參數(shù):size:讀取/寫入的記錄大小nmemb:讀取/寫入的記錄數(shù)返回值:成功返回實際讀入或?qū)懭氲挠涗洈?shù)目失敗返回EOF2.1.18fseek原型:#include<stdio.h>fseeek(FILE*stream,longintoffset,intwhence)其參數(shù)與前面lseek完全一樣2.1.19fgets原型:#include<stdio.h>char*fgets(char*str,intn,FILEstream)說明:fgets函數(shù)從輸入文件流stream里讀取一個字符串。并把它讀到的字符寫到str指向的字符串里,直到:1、遇到換行符,應(yīng)經(jīng)傳輸了n-1個字符,或者達到文件尾。注意:它會把遇到的換行符也傳遞到接收字符串里,再在結(jié)尾加上一個表示結(jié)尾的空字節(jié)\0標準I/O的三種緩沖全緩沖如果緩沖區(qū)寫滿了就寫回內(nèi)核。常規(guī)文件通常是全緩沖的。行緩沖如果用戶程序?qū)懙臄?shù)據(jù)中有換行符就把這一行寫回內(nèi)核,或者如果緩沖區(qū)寫滿了就寫回內(nèi)核。標準輸入和標準輸出對應(yīng)終端設(shè)備時通常是行緩沖的。不帶緩沖用戶程序每次調(diào)庫函數(shù)做寫操作都要通過系統(tǒng)調(diào)用寫回內(nèi)核。標準錯誤輸出通常是無緩沖的,這樣用戶程序產(chǎn)生的錯誤信息可以盡快輸出到設(shè)備。2.2Linux入門知識2.2.1Linux誕生Linux最初版本是1991年,芬蘭赫爾辛基大學(xué)LinusTorvalds開發(fā)的;隨后在網(wǎng)絡(luò)上發(fā)布Linux0.0.2;到1993年底94年底,Linux1.0誕生;1993年Linux加入GNU并遵循公共版權(quán)許可證(GPL),從而為以后的快速發(fā)展創(chuàng)造了條件;1994Linux的第一個商業(yè)發(fā)行版Slackware問世;目前Linux的定位——服務(wù)器市場、桌面市場、嵌入式平臺2.2.2GNU簡介GNU(GNUIsNotUNIX)是自由軟件基金會的一個項目,該項目的目標是開發(fā)一個自由的UNIX版本,這一UNIX版本稱為HURD。GNU項目已經(jīng)開發(fā)了許多高質(zhì)量的編程工具,包括emacs編輯器、著名的GNUC和C++編譯器(gcc和g++),這些編譯器可以在任何計算機系統(tǒng)上運行。所有的GNU軟件和派生工作均適用GNU通用公共許可證,即GPL(GeneralPublicLicense)。GPL允許軟件作者擁有軟件版權(quán),但授予其他任何人以合法復(fù)制、發(fā)行和修改軟件的權(quán)利。2.2.3什么是自由軟件自由軟件(freesoftware)中的free并不是指免費,而是指自由。它賦予使用者四種自由。自由之一:有使用軟件的自由。自由之二:有研究該軟件如何運作的自由,并且得以改寫該軟件來符合使用者自身的需求。取得該軟件的源碼是達成此目的前提。自由之三:有重新散布該軟件的自由,所以每個人都可以有散布自由軟件的自由。自由之四:有改善再利用該軟件的自由,并且可以發(fā)表改寫版供公眾使用,如此一來,整個社群都可以受惠2.2.4目前l(fā)inux的常見發(fā)行版本2.2.5Linux操作系統(tǒng)的架構(gòu)2.2.6Linux下的常用命令命令的工作原理:用戶在提示符下輸入的名令經(jīng)Shell(名令解釋程序)解釋后傳給內(nèi)核輸入命令應(yīng)注意:1、格式:命令【選項】【參數(shù)】2、區(qū)分大小寫2.2.7Linux的文件命名規(guī)則由Linux文件系統(tǒng)的規(guī)定,文件名和目錄名可以包含以下字符:大寫英文字母A-Z、小寫英文字母a-z、數(shù)字0-9、“@”、“_”等。在文件名和目錄中,不得包括的字符有:*?></;&![]|\‘“(){}。不得以”+“和”-“開頭。Linux中的文件名是大小寫敏感的,也就是說,rainbow和Rainbow代表兩個丌同的文件。一個以“.”打頭的文件表明這個文件是隱藏文件(可以用ls-a查看)。Linux系統(tǒng)中文件名的最大長度為255個字符。2.2.8文件權(quán)限文件的權(quán)限,分為三段,分別代表“所有者(u)”、“同組人(g)”、“其它人(o)”的讀(r)、寫(w)、執(zhí)行(x)的權(quán)限。對普通文件而言,“r”代表可以閱讀文件內(nèi)容,“w”代表可以修改或刪除文件內(nèi)容,"x"代表可以將文件作為命令來執(zhí)行(同時需要r權(quán)限)。修改文件權(quán)限:命令——chmod(最常用)

例:[root@localhost~]#chmod664a.txt2.2.9Linux下開發(fā)工具——viVi是“Visualinterface”的簡稱Unix、Linux下的程序開發(fā)工具Unix、Linux下修改配置文件Vi可以執(zhí)行輸入、刪除、查找、替換、塊操作等眾多文本操作Vi不是一個排版程序、它只是一個文本編輯程序Vi是全屏幕文本編輯程序,它沒有菜單,只有命令現(xiàn)常用的為vi的升級版vim2.2.10Vi的安裝使用Vim的安裝:sudoapt-getinstallvimVim的使用:vi<文件名>——創(chuàng)建(如果沒有創(chuàng)建)并進入文件例vihello.cvi編輯器有三種工作模式:命令行模式:剛進入文件即為此模式,此模式下可以移動鼠標、通過鍵盤輸入一些命令完成查找、復(fù)制等功能,或進入底行模式、插入模式插入模式:在命令行模式下輸入i或a進入(最常用為i),只有在命令行模式下才能字符輸入,按【Esc】返回到命令行模式底行模式:在該模式下,用戶可以將文件保存或退出。這一模式下的命令都以“:”開始2.2.11Linux編譯器gcc及其使用編譯如C、C++、ObjectC、Java、Fortran、Pasca等多種語言一個交叉平臺編譯器,適合在嵌入式領(lǐng)域的開發(fā)編譯全稱為GNUCompilerCollection,GNU項目中符合ANSIC標準的編譯系統(tǒng)gcc可以使程序員靈活地控制編譯過程。編譯過程一般可以分為四個階段,每個階段分別調(diào)用不同的工具迚行處理使用格式:gcc【選項】源文件名連接:gcctest.o-otest一般情況下直接由源程序生成可執(zhí)行文件:1、gcctest.c即可生成以a.out命名的可執(zhí)行文件2、gcctest.c–otest(或其他名字)即生成具有自己命名的可執(zhí)行文件執(zhí)行:./可執(zhí)行文件名2.2.12MakefileMakefile需要按照某種語法進行編寫,其中說明了如何編譯各個源文件并連接生成可執(zhí)行文件,并定義了源文件之間的依賴關(guān)系。當修改了其中某個源文件時,如果其他源文件依賴于該文件,則也要重新編譯所有依賴該文件的源文件。Makefile文件的建立:通常采用vimakefile,編輯完成后保存即生成makefile文件一個Makefile文件主要含有一系列的規(guī)則,每條規(guī)則包含以下內(nèi)容:–一個目標(target),即make最終需要創(chuàng)建的文件,如可執(zhí)行文件和目標文件;目標也可以是要執(zhí)行的動作,如“clean”。–一個或多個依賴文件(dependency)列表,通常是編譯目標文件所需要的其他文件。–一系列命今(command),是make執(zhí)行的動作,通常是把指定的相關(guān)文件編譯成目標文件的編譯命令,每個命令占一行,且每個命令行的起始字符必須為TAB字符。Makefile的執(zhí)行保存并退出makefile文件后,輸入make命令如果要使用其他文件作為makefile,則可利用類似下面的make命令選項指定makefile文件:$make-fMakefile.debug2.2.13Make的工作過程首先make按順序讀取makefile中的規(guī)則然后檢查該規(guī)則中的依賴文件與目標文件的時間戳哪個更新如果目標文件的時問戳比依賴文件還早,就按規(guī)則中定義的命令更新目標文件。如果該規(guī)則中的依賴文件又是其他規(guī)則中的目標文件,那么依照規(guī)則鏈不斷執(zhí)行這個過程,直到Makefile文件的結(jié)束,至少可以找到一個不是規(guī)則生成的最終依賴文件,獲得此文件的時間戳然后從下到上依照規(guī)則鏈執(zhí)行目標文件的時間戳比此文件時間戳舊的規(guī)則,直到最頂層的規(guī)則2.2.14Makefile的優(yōu)點通過以上的分析過程,可以看到make的優(yōu)點,因為.o目標文件依賴.c源文件,源碼文件里一個簡單改變都會造成那個文件被重新編譯,并根據(jù)規(guī)則鏈依次由下到上執(zhí)行編譯過程,直到最終的可執(zhí)行文件被重新連接。例如,當改變一個頭文件的時候,由于所有的依賴關(guān)系都在Makefile里,因此不再需要記住依賴此頭文件的所有源碼文件,make可以自動的重新編譯所有那些因依賴這個頭文件而改變了的源碼文件,如果需要,再進行重新連接2.3單向鏈表的實現(xiàn)2.3.1malloc和freemalloc是在堆上分配空間,并返回指向該段存儲空間的地址#include<stdlib.h>void*malloc(size_tsize);voidfree(void*pointer);使用:int*p;p=malloc(100);if(p==NULL){…}2.3.2鏈表在物理內(nèi)存上的存儲head指針是鏈表的頭指針,指向第一個節(jié)點,每個節(jié)點的next指針域指向下一個節(jié)點,最后一個節(jié)點的next指針域為NULL,在圖中用0表示。機構(gòu)圖:2.3.3鏈表的特點每個鏈表有一個頭指針,通過頭指針可以找到第一個節(jié)點,每個節(jié)點都可以通過指針域找到它的后繼,最后一個節(jié)點的指針域為NULL,表示沒有后繼。數(shù)組在內(nèi)存中是連續(xù)存放的,而鏈表在內(nèi)存中的布局是丌規(guī)則的,我們知道訪問某個數(shù)組元素b[n]時可以通過基地址+n×每個元素的字節(jié)數(shù)得到它地址,或者說數(shù)組支持隨機訪問,而鏈表是不支持隨機訪問的,只能通過前一個元素的指針域得知后一個元素的地址,因此只能從頭指針開始順序訪問各節(jié)點。2.3.4鏈表節(jié)點的基本格式#defineMAX16#defineMAXLINE1024typedefstructclient*mylink;structclient{charuser[MAX];charcode[MAX];intfd;mylinknext;};2.3.5鏈表的插入2.4多進程編程2.4.1進程與程序程序(program)是存放在磁盤文件中的可執(zhí)行文件。進程:程序的執(zhí)行實例被稱為進程(process)。進程ID:每個linux進程都一定有一個唯一的數(shù)字標識符,稱為進程ID(processID)。進程ID總是一非負整數(shù)。2.4.2進程的三種狀態(tài)運行狀態(tài)(Running):占用處理機資源;處亍此狀態(tài)的迚程的數(shù)目小于等于CPU的數(shù)目。在沒有其他進程可以執(zhí)行時(如所有進程都在阻塞狀態(tài)),通常會自動執(zhí)行系統(tǒng)的idle進程(相當于空操作)。就緒狀態(tài)(Ready):進程已獲得除處理機外的所需資源,等待分配處理機資源;只要分配CPU就可執(zhí)行??梢园炊鄠€優(yōu)先級來劃分隊列,如:時間片用完->低優(yōu),I/O完成->中優(yōu),頁面調(diào)入完成->高優(yōu)阻塞狀態(tài)(Blocked):由于進程等待某種條件(如I/O操作或進程同步),在條件滿足之前無法繼續(xù)執(zhí)行。該事件發(fā)生前即使把處理機分配給該進程,也無法運行。如:等待I/O操作的完成。2.4.3項目中使用多進程的原因本項目多進程只應(yīng)用在了客戶端原因是在客戶端信息的發(fā)送和接收都是互相獨立的,即并發(fā)執(zhí)行,采用兩個進程一個進程負責(zé)發(fā)送消息,一個進程負責(zé)接收消息,可以順利的實現(xiàn)信息的發(fā)收本項目中服務(wù)器也可以才用多進程,即用多個進程分別處理所連接的各個用戶的信息,但由于使用了select,所以省去了多進程2.4.4進程控制#include<sys/types.h>#include<unistd.h>pid_tfork(void);fork調(diào)用失敗則返回-12.4.5fork用法一個父進程希望復(fù)制自己,使父、子進程同時執(zhí)行不同的代碼段。——網(wǎng)絡(luò)服務(wù)器的經(jīng)典代碼一個進程要執(zhí)行一個不同的程序。——這對shell是常見的情況。在這種情況下,子進程在從fork返回后立即調(diào)用exec函數(shù)。2.4.6fork發(fā)生了什么Fork產(chǎn)生的子進程是對父進程完整的復(fù)制但fork之后返回兩個值,即一次調(diào)用,兩個返回其中的一個返回值是子程序的id號,一個返回為0 》當返回值大于0,即為子進程ID時,父進程執(zhí)行》當返回值等于0,子進程執(zhí)行通過上述原理實現(xiàn)父進程、子進程執(zhí)行不同的代碼段2.4.7fork.c2.4.8代碼分析父進程初始化。父進程調(diào)用fork,這是一個系統(tǒng)調(diào)用,因此進入內(nèi)核。內(nèi)核根據(jù)父進程復(fù)制出一個子進程,父進程和子進程的PCB信息相同,用戶態(tài)代碼和數(shù)據(jù)也相同。因此,子進程現(xiàn)在的狀態(tài)看起來和父迚程一樣,做完了初始化,剛調(diào)用了fork迚入內(nèi)核,還沒有從內(nèi)核返回?,F(xiàn)在有兩個一模一樣的進程看起來都調(diào)用了fork進入內(nèi)核等待從內(nèi)核返回(實際上fork只調(diào)用了一次),此外系統(tǒng)中還有很多別的進程也等待從內(nèi)核返回。是父進程先返回還是子進程先返回,還是這兩個進程都等待,先去調(diào)度執(zhí)行別的進程,這都不一定,取決于內(nèi)核的調(diào)度算法。如果某個時刻父進程被調(diào)度執(zhí)行了,從內(nèi)核返回后就從fork函數(shù)返回,保存在變量pid中的返回值是子進程的id,是一個大于0的整數(shù),因此執(zhí)下面的else分支,然后執(zhí)行for循環(huán),打印“Thisistheparent\n”三次之后終止。如果某個時刻子進程被調(diào)度執(zhí)行了,從內(nèi)核返回后就從fork函數(shù)返回,保存在變量pid中的返回值是0,因此執(zhí)行下面的if(pid==0)分支,然后執(zhí)行for循環(huán),打印“Thisisthechild\n”六次之后終止。fork調(diào)用把父進程的數(shù)據(jù)復(fù)制一份給子進程,但此后二者互不影響,在這個例子中,fork調(diào)用之后父進程和子進程的變量message和n被賦予不同的值,互不影響。父進程每打印一條消息就睡眠1秒,這時內(nèi)核調(diào)度別的進程執(zhí)行,在1秒這樣長的間隙里(對于計算機來說1秒很長了)子進程很有可能被調(diào)度到。同樣地,子進程每打印一條消息就睡眠1秒,在這1秒期間父進程也很有可能被調(diào)度到。所以程序運行的結(jié)果基本上是父子進程交替打印,但這也不是一定的,取決于系統(tǒng)中其它進程的運行情況和內(nèi)核的調(diào)度算法,如果系統(tǒng)中其它進程非常繁忙則有可能觀察到不同的結(jié)果。另外,也可以把sleep(1);去掉看程序的運行結(jié)果如何2.4.9終止進程正常終止:–從main返回–調(diào)用exit–調(diào)用_exit異常終止–調(diào)用abort–由一個信號終止2.4.10正常終止exit和_exit函數(shù)用于正常終止一個程序#include<stdlib.h>voidexit(intstatus);exit則先執(zhí)行一些清除處理.然后進入內(nèi)核清除操作包括調(diào)用執(zhí)行各終止處理程序,關(guān)閉所有標準I/O流#include<unistd.h>void_exit(intstatus);_exit立即進入內(nèi)核2.4.11異常終止信號終止信號是在軟件層次上的對中斷機制的一種模擬原理上,一個進程收到一個信號與處理器收到一個中斷請求是一樣的信號是異步的常用的用來終止進程的函數(shù):#include<signal.h>#include<sys/types.h>intkill(pid_tpid,intsig)例kill(myid,SIGINT);2.5聊天室項目簡介2.5.1項目說明基本架構(gòu):C/S架構(gòu)何為C/S架構(gòu)?即服務(wù)器(server)/客戶端(client)結(jié)構(gòu)2.5.2項目總體講解基本功能:ClientA登陸聊天服務(wù)器前,需要注冊自己的ID和密碼注冊成功后,ClientA就可以通過自己的ID和密碼登陸聊天服務(wù)器多個ClientX可以同時登陸聊天服務(wù)器之后,與其他用戶進行通訊聊天ClientA成功登陸后可以查看當前聊天室內(nèi)其他在線用戶ClientxClientA可以選擇發(fā)消息給某個特定的ClientX,即”悄悄話”功能ClientA可以選擇發(fā)消息全部的在線用戶,即”群發(fā)消息”功能ClientA在退出時需要保存聊天記錄Server端維護一個所有登陸用戶的聊天會的記錄文件,以便備查C語言開發(fā)的思路:C語言是一種面向過程的語言,即傳統(tǒng)的結(jié)構(gòu)化程序設(shè)計(StructuredProgrammingSP)方法在數(shù)據(jù)處理過程中,采用的是自頂向下、分而治之的方法,將整個程序按功能劃分為幾個可獨立編程的子過程模塊,每一子模塊完成指定的子任務(wù),最后,主過程通過調(diào)用各子過程完來成全部處理工作2.5.3根據(jù)架構(gòu)劃分2.5.4用戶錄入從標準輸入接收用戶的錄入,提示用戶輸入相應(yīng)信息可以使用函數(shù)fgets2.5.5信息打包確立自己的通信協(xié)議,即每次傳遞的信息包含哪些這里的協(xié)議可以是一個結(jié)構(gòu)體,打包即將用戶錄入添加到結(jié)構(gòu)體中2.5.6信息發(fā)送、接收讀、寫套接字注:在讀寫時注意類型轉(zhuǎn)換2.5.7信息顯示取出包內(nèi)信息,并輸出2.5.8保存消息將消息寫入到定好的文件中2.5.9傳遞消息采用TCP/ip協(xié)議,采用網(wǎng)絡(luò)編程實現(xiàn)客戶端與服務(wù)器的通信2.5.10服務(wù)器解析消息服務(wù)器收到數(shù)據(jù)后,將數(shù)據(jù)解析,根據(jù)不同的模式執(zhí)行不同的操作處理包括:鏈表操作、信息轉(zhuǎn)發(fā)、信息回應(yīng)等2.5.11實習(xí)目標了解linux下C開發(fā)平臺學(xué)會使用gnu開發(fā)工具了解C語言開發(fā)流程,提高c語言編程能力對所做項目有一定了解,熟悉本項目的開發(fā)思路及所用知識,培養(yǎng)軟件開發(fā)興趣2.6網(wǎng)絡(luò)編程2.6.1字節(jié)序由于丌同的計算機系統(tǒng)采用不同的字節(jié)序存儲數(shù)據(jù),同樣一個4字節(jié)的32位整數(shù),在內(nèi)存中存儲的方式就不同.字節(jié)序分為小端字節(jié)序(LittleEndian)和大端字節(jié)序(BigEndian),Intel處理器大多數(shù)使用小端字節(jié)序,Motorola處理器大多數(shù)使用大端(BigEndian)字節(jié)序;2.6.2網(wǎng)絡(luò)字節(jié)序TCP/IP協(xié)議規(guī)定,網(wǎng)絡(luò)數(shù)據(jù)流應(yīng)采用大端字節(jié)序,即低地址高字節(jié).為使網(wǎng)絡(luò)程序具有可移植性,使同樣的C代碼在大端和小端計算機上編譯后都能正常運行,可以調(diào)用以下庫函數(shù)做網(wǎng)絡(luò)字節(jié)序和主機字節(jié)序的轉(zhuǎn)換2.6.3網(wǎng)絡(luò)字節(jié)序和主機字節(jié)序轉(zhuǎn)換#include<arpa/inet.h>uint32_thtonl(uint32_thostlong);uint16_thtons(uint16_thostshort);uint32_tntohl(uint32_tnetlong);uint16_tntohs(uint16_tnetshort);這些函數(shù)名很好記,h表示host,n表示network,l表示32位長整數(shù),s表示16位短整數(shù)。例如htonl表示將32位的長整數(shù)從主機字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序,例如將IP地址轉(zhuǎn)換后準備發(fā)送。如果主機是小端字節(jié)序,這些函數(shù)將參數(shù)做相應(yīng)的大小端轉(zhuǎn)換然后返回,如果主機是大端字節(jié)序,這些函數(shù)不做轉(zhuǎn)換,將參數(shù)原封不動地返回。2.6.4基于數(shù)據(jù)流的socket編程流程2.6.5socketIntsocket(intfamily,inttype,intprotocol);socket()打開一個網(wǎng)絡(luò)通訊端口,如果成功的話,就像open()一樣返回一個文件描述符,應(yīng)用程序可以像讀寫文件一樣用read/write在網(wǎng)絡(luò)上收發(fā)數(shù)據(jù),如果socket()調(diào)用出錯則返回-1。對于IPv4,family參數(shù)指定為AF_INET即為遵循UNIX網(wǎng)絡(luò)套接字。對于TCP協(xié)議,type參數(shù)指定為SOCK_STREAM,表示面向流的傳輸協(xié)議。(如果是UDP協(xié)議,則type參數(shù)指定為SOCK_DGRAM,表示面向數(shù)據(jù)報的傳輸協(xié)議。)protocol參數(shù)的介紹從略,指定為0即可。2.6.6bindIntbind(intsockfd,conststructsockaddr*myaddr,socklen_taddrlen);bind()成功返回0,失敗返回-1。服務(wù)器程序所監(jiān)聽的網(wǎng)絡(luò)地址和端口號通常是固定不變的,客戶端程序得知服務(wù)器程序的地址和端口號后就可以向服務(wù)器發(fā)起連接,因此服務(wù)器需要調(diào)用bind綁定一個固定的網(wǎng)絡(luò)地址和端口號。bind()的作用是將參數(shù)sockfd和myaddr綁定在一起,使sockfd這個用于網(wǎng)絡(luò)通訊的文件描述符監(jiān)聽myaddr所描述的地址和端口號。2.6.7sockaddr初始化bzero(&servaddr,sizeof(servaddr));servaddr.sin_family=AF_INET;servaddr.sin_addr.s_addr=htonl(INADDR_ANY);servaddr.sin_port=htons(SERV_PORT);首先將整個結(jié)構(gòu)體清零,然后設(shè)置地址類型為AF_INET,網(wǎng)絡(luò)地址為INADDR_ANY,這個宏表示本地的任意IP地址,因為服務(wù)器可能有多個網(wǎng)卡,每個網(wǎng)卡也可能綁定多個IP地址,這樣設(shè)置可以在所有的IP地址上監(jiān)聽,直到不某個客戶端建立了連接時才確定下來到底用哪個IP地址,端口號為SERV_PORT,我們定義為97322.6.8listenintlisten(intsockfd,intbacklog);listen()成功返回0,失敗返回-1。典型的服務(wù)器程序可以同時服務(wù)于多個客戶端,當有客戶端發(fā)起連接時,服務(wù)器調(diào)用的accept()返回并接受這個連接,如果有大量的客戶端發(fā)起連接而服務(wù)器來不及處理,尚未accept的客戶端就處于連接等待狀態(tài),listen()聲明sockfd處于監(jiān)聽狀態(tài),并且最多允許有backlog個客戶端處于連接待狀態(tài),如果接收到更多的連接請求就忽略。2.6.9select定義函數(shù)intselect(intn,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,structtimeval*timeout);函數(shù)說明select()用來等待文件描述符狀態(tài)的改變。參數(shù)n代表最大的文件描述符加1,參數(shù)readfds、writefds和exceptfds稱為描述符組,是用來回傳該描述符的讀,寫或例外的狀況。2.6.10Select的操作select底下的宏提供了處理這三種描述詞組的方式:FD_CLR(intfd,fd_set*set);用來清除描述詞組set中相關(guān)fd的位FD_ISSET(intfd,fd_set*set);用來測試描述詞組set中相關(guān)fd的位是否為真FD_SET(intfd,fd_set*set);用來設(shè)置描述詞組set中相關(guān)fd的位FD_ZERO(fd_set*set);用來清除描述詞組set的全部位參數(shù)timeout為結(jié)構(gòu)timeval,用來設(shè)置select()的等待時間,其結(jié)構(gòu)定義如下structtimeval{time_ttv_sec;time_ttv_usec;};如果參數(shù)timeout設(shè)為NULL則表示select()沒有timeout。2.6.11返回值執(zhí)行成功則返回文件描述符狀態(tài)已改變的個數(shù)2.6.12acceptIntaccept(intsockfd,structsockaddr*cliaddr,socklen_t*addrlen);三方握手完成后,服務(wù)器調(diào)用accept()接受連接,如果服務(wù)器調(diào)用accept()時還沒有客戶端的連接請求,就阻塞等待直到有客戶端連接上來。cliaddr是一個傳出參數(shù),accept()返回時傳出客戶端的地址和端口號。addrlen參數(shù)是一個傳入傳出參數(shù)(value-resultargument),傳入的是調(diào)用者提供的緩沖區(qū)cliaddr的長度以避免緩沖區(qū)溢出問題,傳出的是客戶端地址結(jié)構(gòu)體的實際長度(有可能沒有占滿調(diào)用者提供的緩沖區(qū))。如果給cliaddr參數(shù)傳NULL,表示不關(guān)心客戶端的地址。2.6.13客戶端程序Intconnect(intsockfd,conststructsockaddr*servaddr,socklen_taddrlen);connect()成功返回0,出錯返回-1??蛻舳诵枰{(diào)用connect()連接服務(wù)器,connect和bind的參數(shù)形式一致,區(qū)別在于bind的參數(shù)是自己的地址,而connect的參數(shù)是對方的地址。3實習(xí)總結(jié)3.1實習(xí)中遇到的問題Q1:什么是多文件處理,如何操作?這個問題是我此次實習(xí)時一上來就遇到的問題,因為老師講過,我也遇到過,當我們寫程序時,若只在一個文件中寫,寫的代碼可能會有幾百上千行,維護起來特別麻煩。所以要用到多文件管理,可是,如何調(diào)用文件,如何定義,在主函數(shù)中如何聲明,這是我所不知道的,我也是問了老師兩遍,才弄清楚。多文件,要在主函數(shù)中聲明你要用的函數(shù),并在分文件中定義。其實就這么簡單,必要的頭文件如“stdafx.h”一定要包含進去就可以了。Q2:怎么讀入文件,怎么輸出到文件?這個是我自己看書解決的,我的思路很明確,把文件當做數(shù)據(jù)庫,我輸入的數(shù)據(jù)寫到里面,回來我再調(diào)用,每個函數(shù)都會把文件中的內(nèi)容讀入到結(jié)構(gòu)體數(shù)組中,然后我在查找,修改,刪除,排序等,最后完成操作后,若有變動,則再次寫入到文件中,這樣下次再使用時,就是用戶改過的內(nèi)容。這里比較重要的是要知道文件中有多少條記錄,用到了feof函數(shù)以及fopen,fread,fwrite,fclose函數(shù)。feof是查找文件否到了末尾,其余的就不用說了。Q3:“容錯”處理?這個是比較讓人頭疼的事,你得想到各種情況,比如,你讓用戶輸入數(shù)字來選擇相應(yīng)功能,但是用戶輸入了字母,這個時候就要提示用戶輸入錯誤,并再次出現(xiàn)菜單,這就需要循環(huán)語句,但是我遇到了死循環(huán),就是因為每次用戶輸入一個選項后,會有敲下回車,這個回車會在文件緩沖區(qū)中,下一次scanf()語句執(zhí)行時,會直接得到這個回車,造成死循環(huán)。因此要寫一條語句“吃掉”這個回車。3.2實習(xí)收獲

溫馨提示

  • 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)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論