TCP協(xié)議網(wǎng)絡(luò)編程實(shí)現(xiàn)兩臺(tái)計(jì)算機(jī)通信(詳細(xì)注釋)_第1頁
TCP協(xié)議網(wǎng)絡(luò)編程實(shí)現(xiàn)兩臺(tái)計(jì)算機(jī)通信(詳細(xì)注釋)_第2頁
TCP協(xié)議網(wǎng)絡(luò)編程實(shí)現(xiàn)兩臺(tái)計(jì)算機(jī)通信(詳細(xì)注釋)_第3頁
TCP協(xié)議網(wǎng)絡(luò)編程實(shí)現(xiàn)兩臺(tái)計(jì)算機(jī)通信(詳細(xì)注釋)_第4頁
TCP協(xié)議網(wǎng)絡(luò)編程實(shí)現(xiàn)兩臺(tái)計(jì)算機(jī)通信(詳細(xì)注釋)_第5頁
全文預(yù)覽已結(jié)束

下載本文檔

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

文檔簡(jiǎn)介

1、精選優(yōu)質(zhì)文檔-傾情為你奉上 3.試用C語言編寫一對(duì)在以太網(wǎng)中發(fā)送和接收數(shù)據(jù)幀的應(yīng)用,建議采用Socket的TCP協(xié)議端口,必須提供軟件設(shè)計(jì)方案和流程圖,軟件代碼的每一行都必須加注中文注釋說明設(shè)計(jì)意圖,不得抄襲。(必做題)解答: 編程使用TCP/IP協(xié)議,采用數(shù)據(jù)流的socket套接口,TCP是面向連接的通信協(xié)議,通過三次握手建立連接,通訊完成時(shí)要拆除連接,由于TCP是面向連接的所以只能用于點(diǎn)對(duì)點(diǎn)的通訊。對(duì)比一下,UDP是面向無連接的通訊協(xié)議,UDP數(shù)據(jù)包括目的端口號(hào)和源端口號(hào)信息,由于通訊不需要連接,所以可以實(shí)現(xiàn)廣播發(fā)送,UDP通訊時(shí)不需要接收方確認(rèn),屬于不可靠的傳輸,可能會(huì)出丟包現(xiàn)象。程序采

2、用服務(wù)器/客戶機(jī)模式,下面是服務(wù)器的程序設(shè)計(jì)方案【1】 首先利用socket系統(tǒng)調(diào)用獲得一個(gè)套接口【2】 系統(tǒng)調(diào)用bind將這個(gè)套接口綁定到主機(jī)的某個(gè)端口上【3】 端口開始偵聽有無連接請(qǐng)求,系統(tǒng)調(diào)用listen【4】 沒有就繼續(xù)偵聽,有的話執(zhí)行下一步【5】 接受connect的請(qǐng)求,系統(tǒng)調(diào)用accept(),得到一個(gè)新的套接口描述符,這個(gè)時(shí)候通信管道已經(jīng)完全建立好了【6】 利用這個(gè)新的描述符完成發(fā)送數(shù)據(jù)幀的操作,系統(tǒng)調(diào)用send()【7】 發(fā)送完畢要撤銷套接口下面是完整程序和詳細(xì)注釋清單01 server.c#include#include#include#include#include#in

3、clude#include#include /頭文件#define MYPORT 3490 /定義用于通信的端口號(hào)#define BACKLOG 10 /定義等待隊(duì)列中最多存放的connect請(qǐng)求個(gè)數(shù)main() /主函數(shù)這里開始int sockfd,new_fd; /這兩個(gè)是調(diào)用socket()系統(tǒng)調(diào)用得到的文件描述符 struct sockaddr_in my_addr; /結(jié)構(gòu)體定義,這是自己和對(duì)方的套接口的地址信息struct sockaddr_in their_addr;int sin_size; /其實(shí)這是accept()里面的第三個(gè)參數(shù),這里先定義if(sockfd=socket

4、(AF_INET,SOCK_STREAM,0)=-1) perror(socket); /進(jìn)入正題,首先socket()系統(tǒng)調(diào)用,sockfd就是 exit(1); /所得套接口的文件描述符,如果調(diào)用失敗,perror會(huì) /顯示錯(cuò)誤信息,然后非正常退出my_addr.sin_family=AF_INET; / ADDRESS FAMILY 地址族my_addr.sin_port=htons(MYPORT);/ 把整數(shù)MYPORT轉(zhuǎn)換成“網(wǎng)絡(luò)字節(jié)順序”my_addr.sin_addr.s_addr=INADDR_ANY;/ 使用自己的IP地址, 自動(dòng)填上它所運(yùn)行的機(jī)器的IP地址bzero(&(m

5、y_addr.sin_zero),8);/結(jié)構(gòu)體中剩下的清0上面是第一步,調(diào)用socket()得到了一個(gè)套接口,下面將調(diào)用bind()將其綁定到本地計(jì)算機(jī)的某個(gè)端口上,當(dāng)然這里就是前面定義的那個(gè)端口 if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr)=-1) perror(bind); /如果失敗就顯示bind()調(diào)用出錯(cuò)原因,成功的話 exit(1); /就繼續(xù)往下運(yùn)行 其實(shí)利用TCP/IP協(xié)議進(jìn)行數(shù)據(jù)流的傳輸就像兩個(gè)地方搭個(gè)管道輸送水流一樣,現(xiàn)在這里是水電站,前面兩步已經(jīng)弄好了一個(gè)出水口,下面就要監(jiān)聽對(duì)方是否

6、需要我送水過去,運(yùn)行l(wèi)isten()系統(tǒng)調(diào)用。假如你不希望與遠(yuǎn)程的一個(gè)地址相連,那你就需要等待接入請(qǐng)求并且用各種方法處理它們。處理過程分兩步:首先,你聽-listen(),然后,你接受-accept()(請(qǐng)看下面的內(nèi)容)。if (listen(sockfd,BACKLOG)=-1) /BACKLOG是在進(jìn)入隊(duì)列中允許的連接數(shù)目,進(jìn)入的連接是在隊(duì)列中一直等待直到接受(accept()連接 perror(listen); /在錯(cuò)誤的時(shí)候返回-1,并設(shè)置全局錯(cuò)誤變量errno exit(1); 下面就是接受一個(gè)連接請(qǐng)求了while(1) sin_size=sizeof(struct sockaddr

7、_in); if(new_fd=accept(sockfd,(struct sockaddr *)&their_addr,&sin_size)=-1) perror(accept); /注意這里出現(xiàn)了第二個(gè)文件描述符,如果只想讓一個(gè)連接進(jìn)來,那么你可以使用close()去關(guān)閉原來的文件描述符sockfd來避免同一個(gè)端口更多的連接 continue; /如果沒有成功接受的話就繼續(xù)監(jiān)聽然后accept printf(server:got connection from %sn,inet_ntoa(their_addr.sin_addr);連接上了要輸出一個(gè)反饋信息:server:got conne

8、ction from+客戶端的ip地址然后就把數(shù)據(jù)幀發(fā)送過去,調(diào)用send(),當(dāng)然我們不用去關(guān)心這個(gè)數(shù)據(jù)幀是怎么被包裝的,這些交給下層處理,fork()產(chǎn)生一個(gè)子進(jìn)程用來發(fā)送數(shù)據(jù) if(!fork() if (send (new_fd,hello,world!n,14,0)=-1) perror(send); close(new_fd);exit(0); close(new_fd); 發(fā)送完畢即時(shí)的關(guān)掉套接口while(waitpid(-1,NULL,WNOHANG)0); 最后釋放子進(jìn)程的資源,防止產(chǎn)生僵尸進(jìn)程造成資源沒有釋放。 至此服務(wù)器程序設(shè)計(jì)完畢,下面著手客戶機(jī)的程序設(shè)計(jì),與服務(wù)器相

9、比客戶端的設(shè)計(jì)相對(duì)簡(jiǎn)單一些,其程序設(shè)計(jì)流程大致如下【1】 系統(tǒng)調(diào)用socket()獲得套接口【2】 由于我是要連到遠(yuǎn)方服務(wù)器端口,所以我不必綁定到自己的機(jī)器端口上,故而有了套接口下面可以直接向遠(yuǎn)方主機(jī)發(fā)送connect連接請(qǐng)求【3】 如果connect失敗,那就返回第二步,繼續(xù)connect,直到成功【4】 連接成功后通信管道就建好了,可以調(diào)用recv()來接受數(shù)據(jù)幀【5】 最后把套接口釋放掉下面是完整程序和詳細(xì)注釋清單 02 user.c#include#include#include#include#include#include#include#include /頭文件#define P

10、ORT 3490 / 端口號(hào)定義,這就是將要連接到的端口#define MAXDATASIZE 100 /這個(gè)參數(shù)是一次所能得到的最大字節(jié)數(shù)下面開始主函數(shù),注意main函數(shù)是有參數(shù)的,argc=參數(shù)的個(gè)數(shù)+1,因?yàn)楹瘮?shù)自身算一個(gè)參數(shù),數(shù)組argv用來依次存放指向參數(shù)的指針int main(int argc,char *argv) 前面都是對(duì)一些參數(shù)類型進(jìn)行聲明int sockfd,numbytes; char bufMAXDATASIZE;struct hostent *he;struct sockaddr_in their_addr; 首先檢驗(yàn)main函數(shù)是不是給了1個(gè)參數(shù),是一個(gè)啊得注意i

11、f(argc != 2) fprintf(stderr,usage:client hostnamen); 如果參數(shù)不是一個(gè)就報(bào)錯(cuò)exit(1); 然后非正常退出 然后檢驗(yàn)參數(shù)(其實(shí)這個(gè)參數(shù)就是服務(wù)器的ip地址,參數(shù)的指針就在argv1里面)是否有效,調(diào)用函數(shù)gethostbyname(),它的基本原理就是得到和你主機(jī)名字相匹配的ip地址。if(he=gethostbyname(argv1)=NULL) herror(gethostbyname); 出錯(cuò)的話返回出錯(cuò)信息exit(1); 能運(yùn)行到這一步說明參數(shù)個(gè)數(shù)和參數(shù)內(nèi)容都是正確的,其實(shí)這才是真正的開始調(diào)用socket()得到套接口,sockf

12、d為返回的套接口描述符if(sockfd=socket(AF_INET,SOCK_STREAM,0)=-1) perror(socket); exit(1); 下面的跟之前服務(wù)器端程序差不多,是對(duì)套接口信息初始化their_addr.sin_family=AF_INET;their_addr.sin_port=htons(PORT);their_addr.sin_addr=*(struct in_addr *)he-h_addr);bzero(&(their_addr.sin_zero), 8);可以繼續(xù)用我的那個(gè)比喻,如果服務(wù)器是水庫(kù),并且那里已經(jīng)有個(gè)出口在偵聽是不是有人要水流,那么我是用戶

13、,并且程序運(yùn)行到這我也已經(jīng)有了一個(gè)入口地址,是時(shí)候跟服務(wù)器取得聯(lián)系了,一旦聯(lián)系成功,立馬就會(huì)建立一條管道,下面就是connect()系統(tǒng)調(diào)用 if(connect(sockfd,(struct sockaddr *)&their_addr,sizeof(struct sockaddr)=-1) perror(connect); exit(1); 連接成功,此時(shí)服務(wù)器的listen()監(jiān)聽到了我的connect,并且accept了我,然后send了數(shù)據(jù)幀給我,所以接下來我就得接受數(shù)據(jù)幀了,用到系統(tǒng)調(diào)用recv()if(numbytes=recv(sockfd,buf,MAXDATASIZE,0)

14、=-1) perror(recv); exit(1); 收到的數(shù)據(jù)存放到數(shù)組buf中,對(duì)于字符串?dāng)?shù)組最后一個(gè)停止位記得給加上bufnumbytes=0;把收到的信息顯示出來吧printf(received:%s,buf);最后關(guān)閉套接口,釋放端口close(sockfd);return 0; 至此完成用戶程序的編寫,采用linux編譯環(huán)境,編譯連接后,運(yùn)行調(diào)試在我的電腦上同時(shí)開兩個(gè)窗口,分別模擬服務(wù)器和用戶,鍵入Ifconfig命令查看本機(jī)的ip地址,顯示本地環(huán)回 inet地址 127.0.0.1運(yùn)行 ./server 服務(wù)器開始運(yùn)行然后 ./user 127.0.0.1 用戶程序運(yùn)行運(yùn)行結(jié)果:服務(wù)器端顯示 server:got connection from 1

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論