基于TCP的多線程聊天室實現(xiàn)【實用文檔】doc_第1頁
基于TCP的多線程聊天室實現(xiàn)【實用文檔】doc_第2頁
基于TCP的多線程聊天室實現(xiàn)【實用文檔】doc_第3頁
基于TCP的多線程聊天室實現(xiàn)【實用文檔】doc_第4頁
基于TCP的多線程聊天室實現(xiàn)【實用文檔】doc_第5頁
已閱讀5頁,還剩76頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

基于TCP的多線程聊天室實現(xiàn)【實用文檔】doc文檔可直接使用可編輯,歡迎下載

基于TCP的多線程聊天室實現(xiàn)【實用文檔】doc文檔可直接使用可編輯,歡迎下載Linux網(wǎng)絡(luò)應(yīng)用技術(shù)基于TCP的多線程聊天室設(shè)計基于TCP的多線程聊天室設(shè)計姓名:李元池,宋權(quán)學號:班級:14軟工云計算4班一:設(shè)計思想:創(chuàng)建通信套接字,進行對于客戶端的監(jiān)聽,定義的有一個全局變量intuser_fd[MAX_USER];用來保存已經(jīng)連接的用戶的通信套接字;用戶選擇群聊的時候服務(wù)器會把接收到的信息發(fā)送給除了發(fā)送此消息的其他所有客戶端,用戶選擇私聊則通過服務(wù)器端定義的結(jié)構(gòu)體structuser_mess{charmessage[100];charname[20];intk;}User[10];中的k;來判斷次編號對應(yīng)的客戶套接字,把此消息發(fā)送給指定的客戶端!利用shocket套接字進行對于信息的傳遞,同時shocket套接字也是一種對于信息識別的判斷依據(jù),根據(jù)套接字可以找到接受的信息的意圖,并且進行處理相應(yīng)的信息,而且服務(wù)器還可以通過對于shocket的識別,然后判斷哪個客戶發(fā)送的信息,然后進行轉(zhuǎn)發(fā)個其他客戶端,進而實現(xiàn)客戶與客戶之間的通信。服務(wù)器相當于一個對于客戶端發(fā)送的信息進行轉(zhuǎn)發(fā)的平臺,當客戶端的信息發(fā)送過來后,服務(wù)器會自動通過套接字將信息在全部轉(zhuǎn)發(fā)給其他的客戶,實現(xiàn)客戶端之間的通信二:流程圖服務(wù)器(sever.c)客戶端服務(wù)器(sever.c)客戶端(client.c)客戶端發(fā)過來其它數(shù)字如1,2,3,….則服務(wù)器會根據(jù)儲存在user_fd[],數(shù)組的下標找到對應(yīng)的客戶端套接字,并把私聊消息正確的發(fā)送給該客戶端!接收私聊消息請求客戶端發(fā)送過來-1,則把該消息發(fā)送給其他所有在線客戶端發(fā)送選項為-1進入公聊連接成功后創(chuàng)建兩個線程th1,th2用于發(fā)送和接收服務(wù)器的信息客戶端在服務(wù)器監(jiān)聽的時候發(fā)送連接請求!acceptYN客戶連接在服務(wù)器先開啟監(jiān)聽服務(wù),等待客戶端連接后再運行客戶端代碼……命令行參數(shù):IP+端口號+昵稱開啟監(jiān)聽listen……客戶端發(fā)過來其它數(shù)字如1,2,3,….則服務(wù)器會根據(jù)儲存在user_fd[],數(shù)組的下標找到對應(yīng)的客戶端套接字,并把私聊消息正確的發(fā)送給該客戶端!接收私聊消息請求客戶端發(fā)送過來-1,則把該消息發(fā)送給其他所有在線客戶端發(fā)送選項為-1進入公聊連接成功后創(chuàng)建兩個線程th1,th2用于發(fā)送和接收服務(wù)器的信息客戶端在服務(wù)器監(jiān)聽的時候發(fā)送連接請求!acceptYN客戶連接在服務(wù)器先開啟監(jiān)聽服務(wù),等待客戶端連接后再運行客戶端代碼……命令行參數(shù):IP+端口號+昵稱開啟監(jiān)聽listen……輸出錯誤信息連接成功后創(chuàng)建兩個線程th1,th2用于發(fā)送和接收服務(wù)器的信息連接成功后創(chuàng)建一個線程,處理該用戶發(fā)送過來的消息和選項輸出錯誤信息連接成功后創(chuàng)建兩個線程th1,th2用于發(fā)送和接收服務(wù)器的信息連接成功后創(chuàng)建一個線程,處理該用戶發(fā)送過來的消息和選項發(fā)送其它數(shù)字則把消息私聊發(fā)送給該客戶端發(fā)送其它數(shù)字則把消息私聊發(fā)送給該客戶端三:分工合作李元池負責服務(wù)器端的編寫,宋權(quán)負責客戶端的編寫,在寫的過程中商量好用于收發(fā)消息的結(jié)構(gòu)體保持一致。四:運行步驟及注意事項:在服務(wù)器開啟監(jiān)聽服務(wù)之后,啟用客戶端段進行連接,服務(wù)器程序編譯:gcc2_sever.c–osever–lpthread?? 運行:./s客戶端程序編譯:gcc1_client.c–oclient–lpthread? ?運行:./c+服務(wù)器的IP+端口號+你的昵稱目前代碼存在的問題有:用戶昵稱重復(fù)處理;異常退出處理;五:運行截圖?開啟一個服務(wù)器和三個客戶端昵稱分別為:李元池,更淵博,許陽,1:(群聊)李元池發(fā)送一個"Hello!everybody!”的消息:2:私聊:李元池給客戶端2更淵博發(fā)送消息:3:許陽給客戶端1,李元池發(fā)送消息:(????)??嗨boby!六:個人心得總結(jié)這兩個星期的課余時間主要和宋權(quán)一起寫了Linux網(wǎng)絡(luò)編程的大作業(yè),當然學習的時候遇到了許多問題,比如:實踐做聊天室的時候問題百出,剛開始的時候不知道怎么實現(xiàn)多個客戶端通信,而通過測試發(fā)現(xiàn)每次客戶端連接時的套接字不一樣,都是從開始隨著客戶端連接的增多而遞增的,所以我把每次連接時的套接字都存到了數(shù)組里,接著問題是客戶端連接的時候要嗎不能做到同步發(fā)送,要嗎有的客戶端收不到信息,又或者是服務(wù)器多轉(zhuǎn)發(fā)幾次,通過上網(wǎng)搜索和交流發(fā)現(xiàn)是沒有實現(xiàn)并發(fā),而實現(xiàn)并發(fā)的方式有i/o多線路,多進程和多線程,而我用的是多線程實現(xiàn)的并發(fā)的。這些問題解決后,群聊實現(xiàn)了;那么,私聊呢,該如何實現(xiàn),在客戶端建立一個結(jié)構(gòu)體用于向服務(wù)器發(fā)送和接受消息,而在服務(wù)器里面這有一個結(jié)構(gòu)體數(shù)組保存鏈接在線的客戶端消息,還有一個套接字描述符的數(shù)組用于保存客戶端的套接字,服務(wù)器在接收到客戶端發(fā)過來的消息時會判斷客戶的發(fā)送選項,根據(jù)選項來找到對應(yīng)下標的客戶端套接字并把消息發(fā)送給該客戶端.通過此次雖然學到了不少,但是自身問題缺點也暴露了很多,最主要的是學到了提高如何處理問題的能力,遇到問題時該如何查找問題產(chǎn)生的原因,該如何解決問題,解決問題時的思路思想;自身問題就是還是自己思路比較狹窄,學東西比較慢,感覺學過之后就忘了??偟膩碚f通過這兩個星期的學習學的東西還挺多的。七:附錄客戶端代碼!//Client.cpp#include〈stdio.h〉#include〈netinet/in.h>#include<sys/socket。h>#include<sys/types。h>#include〈string。h>#include<stdlib.h>#include<netdb.h>#include〈unistd.h〉#include<signal.h>#include<time.h>#include<errno.h>#defineMAX_SIZE100void*send_fun(void*arg);void*recv_fun(void*arg);voiditoa(inti,char*string){intpower,j;j=i;for(power=1;j〉=10;j/=10)power*=10;for(;power>0;power/=10){*string++=’0’+i/power;i%=power;}*string='\0';}voidshow_system_time()?//得到當前系統(tǒng)時間{time_ttimep;structtm*p_curtime;char*time_tmp;time_tmp=(char*)malloc(2);memset(time_tmp,0,2);time(&timep);p_curtime=localtime(&timep);printf("(%d:%d:%d)\n",p_curtime-〉tm_hour,p_curtime->tm_min,p_curtime—>tm_sec);}structuser_messageum;structuser_message{ charmessage[100]; charname[20]; intl;//用戶標識};voidmenu() {?? printf(”\t在輸入消息后回車,\n"); ?printf(”\t然后再輸入用戶客戶端的編號,進入私聊發(fā)送給對應(yīng)用戶\n”);??printf(”\t當輸入—1的時候為,為群聊!\n");? printf("\t輸入消息為quit的時候退出該聊天室\n”);?}intmain(intargc,char*argv[]){structsockaddr_inclientaddr;//定義地址結(jié)構(gòu)pid_tpid;intn,clientfd;//定義客戶端套接字structhostent*host;char*buf,*buf_r;if(argc<3){printf(”usage:\n”);printf("%shostportname\n",argv[1]);exit(1);}printf(”%s\n”,argv[3]); strcpy(,argv[3]);host=gethostbyname(argv[1]);//服務(wù)器IPclientaddr.sin_family=AF_INET;clientaddr.sin_port=htons((uint16_t)atoi(argv[2]));clientaddr。sin_addr=*((structin_addr*)host->h_addr);bzero(&(clientaddr.sin_zero),0);if((clientfd=socket(AF_INET,SOCK_STREAM,0))==—1)//綁定客戶端套接字{perror(”socket\n");exit(1);}if(connect(clientfd,(structsockaddr*)&clientaddr,sizeof(structsockaddr))==—1)//連接服務(wù)端{perror("connect\n”);exit(1);}elsemenu();?pthread_tth1,th2;?if(pthread_creat(yī)e(&th1,NULL,send_fun,(void*)&clientfd))?{? perror(”createthreadfail"); exit(1); } if(pthread_create(&th2,NULL,recv_fun,(void*)&clientfd))?{ perror("createthreadfail”); exit(1); } pthread_join(th1,NULL);?pthread_join(th2,NULL);?as:return0;}void*send_fun(void*arg){ intsfd=*((int*)arg); while(1) {? printf("輸入要發(fā)送的信息:");??bzero(um.message,100);? scanf("%s",um.message); ?printf(”發(fā)送選項(-1—>群聊):”); scanf("%d",&um。l);??if(um.l!=—1)? strcat(yī)(um.message,”(私密消息)”); ?intn=send(sfd,(char*)&um,sizeof(um),0);??if(n!=sizeof(um))??{ printf("sendfail!\n"); } }}void*recv_fun(void*arg){ intsfd=*((int*)arg); //charrecv_message[100]; structuser_messagemy;?while(1) {? intn=recv(sfd,(char*)&my,sizeof(my),0);? if(n==-1) { printf(”recvfail!\n"); ?exit(1);? } //get_system_time(time_str); printf(”\n收到來自%s的消息:%s",my。name,my。message);? show_system_time();?}}服務(wù)器端代碼!//Sever。c#include<stdio.h〉#include〈ctype。h〉#include<sys/socket.h>#include〈arpa/inet.h>#include<strings.h>#include〈string.h>#include<stdlib.h>#include<pthread.h〉#include〈time.h>#defineMAX_LINE100#defineMAX_USER10intuser_fd[MAX_USER];structuser_mess{ charmessage[100]; charname[20];?intk;};voidshow_system_time()?//得到當前系統(tǒng)時間{time_ttimep;structtm*p_curtime;char*time_tmp;time_tmp=(char*)malloc(2);memset(time_tmp,0,2);time(&timep);p_curtime=localtime(&timep);printf(”(%d:%d:%d)\n”,p_curtime-〉tm_hour,p_curtime—>tm_min,p_curtime—>tm_sec);}void*recv_fun(void*arg){ intfd=*((int*)arg); structuser_messum;?intk; while(1) {? intn=recv(fd,(char*)&um,sizeof(um),0);? inti;? if(n==-1)??{?? printf("recvfail!\n”); ? exit(1); ?} for(i=0;i〈MAX_USER;i++)? {?? if(fd==user_fd[i])???break;? }??printf("接收來自客戶端%d,%s的消息:%s",i,,um.message);? show_system_time();? printf("\n"); ?if(um。k==-1) {???for(i=0;i〈MAX_USER;i++) {? if((user_fd[i]!=fd)&&(user_fd[i]!=-1)) send(user_fd[i],(char*)&um,sizeof(um),0); ??} ?}? else? {?? send(user_fd[um.k],(char*)&um,sizeof(um),0);??}?}}intmain(){?structsockaddr_insin; structsockaddr_incin;?intl_fd; socklen_tlen;?charbuf[MAX_LINE];//緩存區(qū)?charaddr_p[16];//存儲客戶端IP?unsignedshortintport=3889; intn;?bzero(&sin,sizeof(sin));?sin。sin_family=AF_INET; sin.sin_addr.s_addr=INADDR_ANY; sin.sin_port=htons(port); if((l_fd=socket(AF_INET,SOCK_STREAM,0))==-1) { ?perror("failtocreatesocket");? exit(1); }?if(bind(l_fd,(structsockaddr*)&sin,sizeof(sin))==-1) {??perror("failtobind");??exit(1);?}?if(listen(l_fd,10)==—1) {? perror("failtolisten"); ?exit(1); } inti; for(i=0;i<MAX_USER;i++)? user_fd[i]=-1; printf("等待客戶端連接。.。.。.\n"); pthread_tth1; while(1) { i=1;? for(i=1;i<MAX_USER;i++) { if(user_fd[i]==-1)? {? ?break;? ?} ?}? if((user_fd[i]=accept(l_fd,(structsockaddr*)&cin,&len))==-1)? { ?perror("failtoaccept”);?? exit(1); ?} else? ?printf("新消息:客戶端%d已連接.。。。..\n",i); ?pthread_create(&th1,NULL,recv_fun,(void*)&user_fd[i]);?} return0;?} 開放性實驗報告題目:基于ARM的多線程應(yīng)用程序設(shè)計院系名稱:電氣工程學院專業(yè)班級:自動1302學生姓名:張鵬濤學號:201323020219指導(dǎo)教師:張曉東成績:成績:指導(dǎo)老師簽名:目錄TOC\o"1-3”\h\uHYPERLINK\l_Toc233581系統(tǒng)概述與設(shè)計要求PAGEREF_Toc233581HYPERLINK\l_Toc46671.1系統(tǒng)概述PAGEREF_Toc46671HYPERLINK\l_Toc121361.2設(shè)計要求PAGEREF_Toc121362286422方案論證PAGEREF_Toc2864222。1實現(xiàn)方法PAGEREF_Toc284922.2線程優(yōu)勢PAGEREF_Toc300312HYPERLINK\l_Toc197593硬件設(shè)計PAGEREF_Toc197593HYPERLINK\l_Toc255393.1樹莓派接口驅(qū)動LED電路設(shè)計934軟件設(shè)計PAGEREF_Toc248624HYPERLINK\l_Toc47954。1驅(qū)動三色LED燈PAGEREF_Toc47954HYPERLINK\l_Toc312464.1.1驅(qū)動實現(xiàn)方法PAGEREF_Toc3124644。1.2wiringPi庫安裝和軟件編程PAGEREF_Toc922044.2服務(wù)器和客戶端PAGEREF_Toc1868754.2。1服務(wù)器設(shè)計方法PAGEREF_Toc269845HYPERLINK\l_Toc128844.2.2客戶端設(shè)計方法PAGEREF_Toc128845HYPERLINK\l_Toc42335系統(tǒng)調(diào)試PAGEREF_Toc42336HYPERLINK\l_Toc25772設(shè)計心得PAGEREF_Toc257726HYPERLINK\l_Toc3827參考文獻PAGEREF_Toc38277HYPERLINK\l_Toc829附錄1(LED驅(qū)動程序)8298HYPERLINK\l_Toc22383附錄2(服務(wù)器程序)PAGEREF_Toc2238310附錄3(客戶端程序代碼)PAGEREF_Toc26713161系統(tǒng)概述與設(shè)計要求1.1系統(tǒng)概述本系統(tǒng)設(shè)計是基于樹莓派開發(fā)板上實現(xiàn)的,樹莓派由注冊于英國的慈善組織“RaspberryPi基金會"開發(fā),Eben·Upton/?!ざ蚱疹D為項目帶頭人。2012年3月,英國劍橋大學埃本·阿普頓(EbenEpton)正式發(fā)售世界上最小的臺式機,又稱卡片式電腦,外形只有信用卡大小,卻具有電腦的所有基本功能,這就是RaspberryPi電腦板,中文譯名"樹莓派".它是一款基于ARM的微型電腦主板,以SD/MicroSD卡為內(nèi)存硬盤,卡片主板周圍有1/2/4個USB接口和一個10/100以太網(wǎng)接口(A型沒有網(wǎng)口),可連接鍵盤、鼠標和網(wǎng)線,同時擁有視頻模擬信號的電視輸出接口和HDMI高清視頻輸出接口,以上部件全部整合在一張僅比信用卡稍大的主板上,具備所有PC的基本功能。而樹莓派2具有900MHz內(nèi)核頻率,4核ARMCortex—A7,1GB內(nèi)存,帶MicroSD卡插槽(支持通過它啟動Linux操作系統(tǒng),如Fedora),40PIN接口(可以增加驅(qū)動外設(shè))。本系統(tǒng)設(shè)計正式在樹莓派2環(huán)境下開發(fā)實現(xiàn)多線程設(shè)計,設(shè)計的主要功能就是兩個客戶端通過服務(wù)器互相收發(fā)信息。1.2設(shè)計要求要求多個客戶端能夠同時連接服務(wù)器,而服務(wù)器需要創(chuàng)建線程來管理這多個客戶端,并且能夠把一個客戶端發(fā)來的數(shù)據(jù)進行解析,發(fā)給另一個客戶端,實現(xiàn)兩個甚至多個客戶端互相收發(fā)信息。能夠通過驅(qū)動三色燈來發(fā)現(xiàn)系統(tǒng)運行的狀態(tài),紅色說明有錯誤發(fā)生,綠色說明正在正常運行,藍色說明有用戶連接,綠色說明有客戶端互相收發(fā)信息。2方案論證2.1實現(xiàn)方法要實現(xiàn)服務(wù)器同時管理兩個甚至多個客戶端,就必須引入進程或線程。2.2線程優(yōu)勢一是和進程相比,它是一種非?!惫?jié)儉"的多任務(wù)操作方式。進程是系統(tǒng)中程序執(zhí)行和資源分配的基本單位。我們知道,在Linux系統(tǒng)下,啟動一個新的進程必須分配給它獨立的地址空間,建立眾多的數(shù)據(jù)表來維護它的代碼段、堆棧段和數(shù)據(jù)段,這就導(dǎo)致了進程在進行切換等操作起到了現(xiàn)場保護作用,這是一種"昂貴"的多任務(wù)工作方式。但是為了進一步減少處理機的空轉(zhuǎn)時間支持多處理器和減少上下文切換開銷,進程演化中出現(xiàn)了另外一個概念,這就是線程,也被人稱為輕量級的進程。它是一個進程內(nèi)的基本調(diào)度單位。線程是在共享的內(nèi)存空間中并發(fā)的多道執(zhí)行路徑,它們共享一個進程的資源,比如文件描述符和信號處理等。因此,大大減少了上下文切換的開銷。二是線程間方便的通信機制。對不同進程來說,它們具有獨立的數(shù)據(jù)空間,要進行數(shù)據(jù)的傳遞只能通過通信的方式進行,這種方式不僅費時,而且很不方便。線程則不然,由于同一進程下的線程之間共享數(shù)據(jù)空間,所以一個線程的數(shù)據(jù)可以直接為其它線程所用,這不僅快捷,而且方便。當然,數(shù)據(jù)的共享也帶來其他一些問題,有的變量不能同時被兩個線程所修改,有的子程序中聲明為static的數(shù)據(jù)更有可能給多線程程序帶來災(zāi)難性的打擊,這些正是編寫多線程程序時最需要注意的地方.3硬件設(shè)計3.1樹莓派接口驅(qū)動LED電路設(shè)計圖3.1從圖3.1可以知道,要想讓三色燈的紅色亮起來,首先控制樹莓派GPIO.27引腳輸出低電平,同理可以控制GPIO.28、GPIO29引腳電瓶來控制綠、藍LED的啟動和關(guān)閉。樹莓派開發(fā)板上的相關(guān)引腳如圖3.2。圖3.24軟件設(shè)計4.1驅(qū)動三色LED燈4.1.1驅(qū)動實現(xiàn)方法控制引腳電瓶的高低就能實現(xiàn)控制LED燈的變化,實際上三色LED可以顯示無數(shù)種顏色,要想超過三種顏色的顯示實現(xiàn),就必須引入PWM.PWM是模擬脈寬調(diào)制來控制輸出引腳的實際輸出電瓶大小,此系統(tǒng)可以控制引腳從0~3.3V變化來顯示不同的顏色.wiringPi適合那些具有C語言基礎(chǔ),在接觸樹莓派之前已經(jīng)接觸過單片機或者嵌入式開發(fā)的人群。wiringPi的API函數(shù)和arduino非常相似,這也使得它廣受歡迎。作者給出了大量的說明和示例代碼,這些示例代碼也包括UART設(shè)備,I2C設(shè)備和SPI設(shè)備等。4.1。2wiringPi庫安裝和軟件編程首先需要在樹莓派上安裝wiringPi庫,我們選擇直接在網(wǎng)上下載安裝源碼,輸入命令:cd~進入根目錄下,輸入命令:gitclonegit://git.drog/wiringPi從網(wǎng)上下載源碼包,輸入命令cdwiringPi進入安裝包目錄下,依次輸入命令:configuremakemakeinstall來配置、編譯和安裝,最后輸入命令sudo./build來執(zhí)行編譯之后生成的可執(zhí)行文件,完成安裝。最后輸入命令:gpioreadall會出來引腳圖來確定已經(jīng)安裝成功。接下來就需要運用庫的軟件編程來驅(qū)動led燈啦,在寫C文件時首先要加入庫的頭文件:#include<wiringPi。h>和C語言必要的頭文件:#include〈stdio.h>,然后還需要加入實現(xiàn)軟件PWM的頭文件:#include<softPwm。h〉。接下來我們就需要運用庫的API函數(shù)wiringPiSetup()初始化wiringPi,若初始化失敗會返回—1;然后運用庫的API函數(shù)softPwmCreate()創(chuàng)建軟件PWM,此函數(shù)有3個輸入?yún)?shù),分別是控制引腳號,PWM最小值,PWM最大值;運用庫的API函數(shù)softPwmWrite()寫PWM的值,此函數(shù)有2個輸入?yún)?shù),分別是控制那個引腳號,寫入的PWM的值,此值需要在最小最大值之間。完整代碼如附錄1。4.2服務(wù)器和客戶端4.2.1服務(wù)器設(shè)計方法為了方便起見,我們把服務(wù)器和客戶端都定義在本地IP上進行測試,服務(wù)器端的話,首先我們需要把主函數(shù)傳入的端口號記錄下來,并且利用C語言標準函數(shù)at(yī)oi轉(zhuǎn)換成整型值.接著我們定義兩個整型數(shù)組來存放兩個客戶端的套接字,然后我們根據(jù)端口去創(chuàng)建服務(wù)器,創(chuàng)建服務(wù)器需要幾個函數(shù)來實現(xiàn),第一個就是socket()函數(shù)來創(chuàng)建一個服務(wù)器的套接字,此函數(shù)有3個輸入?yún)?shù),我們選擇ipv4協(xié)議族,流式Socket,TCP協(xié)議類型。然后根據(jù)端口號和本地IP配置服務(wù)器,之后就是調(diào)用綁定bind(),監(jiān)聽listen()函數(shù)來完成服務(wù)器的創(chuàng)建.之后就是根據(jù)創(chuàng)建的套接字來進行循環(huán),如果有客戶端連接,就保存客戶端套接字創(chuàng)建一個線程去處理,此處我們以兩個客戶端為例來進行操作。若是套接字編號0發(fā)來消息,我們就轉(zhuǎn)發(fā)給套接字編號1,若是超過2個的客戶端連接進來我們直接關(guān)閉創(chuàng)建的線程就行,之后要是有客戶端掉線,就把線程和客戶端一塊銷毀。具體代碼實現(xiàn)見附錄24。2。2客戶端設(shè)計方法首先我們封裝三個函數(shù),分別是連接、讀數(shù)據(jù)、寫數(shù)據(jù),開始就調(diào)用連接函數(shù),在連接函數(shù)里我們創(chuàng)建客戶端并通過輸入的服務(wù)器ip和端口去連接服務(wù)器,然后我們創(chuàng)建兩個線程分別是讀和寫,在讀函數(shù)里我們不間斷讀鍵盤數(shù)據(jù)并發(fā)送給服務(wù)器,在寫函數(shù)里不間斷的讀服務(wù)器發(fā)來的數(shù)據(jù)并顯示在屏幕上.具體代碼實現(xiàn)見附錄3。5系統(tǒng)調(diào)試此系統(tǒng)的調(diào)試,我們選擇Linux虛擬機模擬調(diào)試,首先運行服務(wù)器和兩個客戶端,然后客戶端連接服務(wù)器,之后兩個客戶端互相收發(fā)數(shù)據(jù).為了方便起見,我在PC機上運行和仿真,首先安裝虛擬機VMware8。0,然后安裝VMwareTools,虛擬機的工具是為了共享電腦上的文件,這樣可以在電腦上編寫代碼,在虛擬機上編譯運行。編譯服務(wù)器的代碼,輸入命令gccserver.c—oserver.exe-lpthread,回車之后會生成server.exe可執(zhí)行文件,之后我們運行服務(wù)器,輸入命令./server.exe6789,運行服務(wù)器,其中6789為輸入的端口號。之后編譯客戶端代碼,輸入命令gccclient。c-oclient。exe—lpthread,回車之后會生成client.exe可執(zhí)行文件,我們事先查看虛擬機ip,輸入命令ifconfig回車就能看到虛擬機本機ip,為我們客戶端連接服務(wù)器所用。之后我們運行客戶端一,輸入命令。/client.exe192.168。20。1096789,回車,然后用同樣的命令運行客戶端二,之后我們在一個客戶端輸入信息回車,在另一個客戶端就能接收到,具體運行結(jié)果如圖5.1,5。2,5.3。圖5。1圖5.2圖5.3設(shè)計心得此次開發(fā)性試驗設(shè)計讓我收獲甚多.一是要有一個積極的心態(tài),獨立解決問題的意識,培養(yǎng)扎實基礎(chǔ)的認識。不要什么東西都感覺跟簡單(很多東西可能是看似簡單)就不去做了或者不屑一做,以至于性網(wǎng)上搜搜就可以了,這樣很不好。有自己的東西有自己的付出才會有程序運行成功時的喜悅和小自豪,這樣也有助于培養(yǎng)自己的興趣.要時刻牢記態(tài)度決定一切。其次是興趣,感覺學習工作中興趣很關(guān)鍵,只是一個引發(fā)人積極性的問題,有了興趣就自覺了,效率自然就高了。再次要敢于嘗試和挑戰(zhàn)。不要安于現(xiàn)成的程序,而且不要害怕失敗,在程序調(diào)試的過程中這點尤為重要,“發(fā)現(xiàn)出問題然后解決問題”是一個積累經(jīng)驗的過程,而且很高效。最后要不懈追求。對于源代碼進行不斷的完善,要盡可能的實現(xiàn)課題所要求的功能.對于初學者或者開發(fā)較少的人來說,大量大寫程序還是有必要的,但同時要注意思考,理解其實現(xiàn)的內(nèi)在意義。還可以自己添加一些有意義的功能來實現(xiàn)。當看到自己編寫的程序正常運行時,興趣也會隨之而來,樂此不疲,形成一個良性循環(huán).

短短一周的開放性ARM多線程設(shè)計很快結(jié)束了,我發(fā)現(xiàn)我對嵌入式這個方向、對嵌入式技術(shù)、對Linux都有了新的認識。通過這次的編程,我了解到,要真真正正的掌握計算機程序還不是一件簡單容易的事兒,但真正掌握后,它帶給我們的將是無窮的便捷與科技,我喜歡高端便捷的生活。我希望我能做計算機這個萬能機器人的主人而不是奴隸,我會努力加油的!參考文獻[1]徐千洋.Linux

C函數(shù)庫參考手冊.[M]中國青年出版社.2002

[2]馬忠梅,馬廣云,徐英慧,田譯.ARM嵌入式處理結(jié)構(gòu)與應(yīng)用基礎(chǔ)[M].北京航空航天大學出版社。2002

[3]鄒思鐵。嵌入式Linux設(shè)計與應(yīng)用[M].北京清華大學出版社。2002

[4]杜春雷。ARM體系結(jié)構(gòu)與編程[M].清華大學出版社。2003

[5]田澤。嵌入式系統(tǒng)開發(fā)與應(yīng)用[M]。北京航空航天大學出版社。2005

[11]陳鑫。嵌入式軟件技術(shù)的現(xiàn)狀與發(fā)展動向[M].軟件世界。2001

[6]田澤。嵌入式系統(tǒng)開發(fā)與應(yīng)用實驗教程[M].北京航空航天大學出版社.2004

[7]Alessandro

Rubini,Jonat(yī)han

Corbet.Linux設(shè)備驅(qū)動程序[M].中國電力出版社.2002附錄1(LED驅(qū)動程序)#include<wiringPi.h>#include〈softPwm.h>#include〈stdio.h>#defineucharunsignedchar#defineLedPinRed27#defineLedPinGreen28#defineLedPinBlue29voidledInit(void){softPwmCreat(yī)e(LedPinRed,0,100);softPwmCreat(yī)e(LedPinGreen,0,100);softPwmCreate(LedPinBlue,0,100);}voidledColorSet(ucharr_val,ucharg_val,ucharb_val){softPwmWrite(LedPinRed,r_val);softPwmWrite(LedPinGreen,g_val);softPwmWrite(LedPinBlue,b_val);}intmain(void){inti;if(wiringPiSetup()==—1){printf("setupwiringPifailed?。ⅲ?;return1;}ledInit();while(1){ledColorSet(0xff,0x00,0x00);//reddelay(500);ledColorSet(0x00,0xff,0x00);//greendelay(500);ledColorSet(0x00,0x00,0xff);//bluedelay(500);}return0;}附錄2(服務(wù)器程序)#include<stdio.h>#include<stdlib.h〉#include<string.h>#include<signal.h>#include〈unistd.h>#include<error。h>#include<errno。h>#include〈fcntl.h〉#include<sys/types。h>#include<sys/socket。h>#include<sys/epoll.h>#include<netinet/in.h〉#include〈arpa/inet。h>#include<pthread。h>#defineBUFSIZE1024intsocket_client[2];intsocket_creat(yī)e(intport){intst=socket(AF_INET,SOCK_STREAM,0);inton=1;if(setsockopt(st,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))==—1){printf("setsockoptisfailed%s\n",strerror(errno));return0;}structsockaddr_inaddr;memset(&addr,0,sizeof(addr));addr.sin_family=AF_INET;addr。sin_port=htons(port);addr。sin_addr。s_addr=htonl(INADDR_ANY);if(bind(st,(structsockaddr*)&addr,sizeof(addr))==-1){printf("zhang.pt:bindisfailed%s\n",strerror(errno));return0;}if(listen(st,300)==-1){printf(”zhang。pt:listenisfailed%s\n",strerror(errno));return0;}returnst;}voiddeliver(intindex,constchar*buf,ssize_tlen){ssize_trc=0;if(index==0){if(socket_client[1]==0){printf("%d:usernotonline\n",index);}else{rc=send(socket_client[1],buf,len,0);printf(”send:%s,send:%ubytes\n",buf,rc);if(rc<=0){if(rc==0)printf("zhang.pt:sendfailed,disconnection,\n");elseprintf("zhang.pt:sendfailed,%s\n",strerror(errno));}}}if(index==1){if(socket_client[0]==0){printf("%d:usernotonline\n”,index);}else{rc=send(socket_client[0],buf,len,0);printf("send:%s,send:%ubytes\n",buf,rc);if(rc〈=0){if(rc==0)printf("zhang.pt:sendfailed,disconnection,\n”);elseprintf(”zhang.pt:sendfailed,%s\n",strerror(errno));}}}}voidsocket_work(intindex){charbuf[BUFSIZE];ssize_trc=0;while(1){memset(buf,0,sizeof(buf));rc=recv(socket_client[index],buf,sizeof(buf),0);if(rc<=0){if(rc==0)printf(”%d:recvdisconnection\n",index);elseprintf(”%d:recvfailed,%s\n”,index,strerror(errno));close(socket_client[index]);socket_client[index]=0;break;}else{printf(”%d:recv:%s,recv:%ubytes\n",index,buf,rc);deliver(index,buf,rc);}}}void*socket_handle(void*arg){intclient_st=*(int*)arg;free((int*)arg);printf("zhang.pt:handle_threadisbegin\n");intindex=0;if(socket_client[0]==0){socket_client[0]=client_st;}else{if(socket_client[1]==0){socket_client[1]=client_st;index=1;}else{close(client_st);returnNULL;}}socket_work(index);printf("zhang。pt:handle_threadisend\n");returnNULL;}voidsockaddr_toa(conststructsockaddr_in*addr,char*IPAddr){unsignedchar*p=(unsignedchar*)&(addr—>sin_addr.s_addr);sprintf(IPAddr,"%u。%u。%u.%u",p[0],p[1],p[2],p[3]);}voidsocket_accept(intst){pthread_tthr_d;pthread_attr_tattr;pthread_attr_init(&at(yī)tr);pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);structsockaddr_inclient_addr;socklen_tlen=sizeof(client_addr);while(1){memset(&client_addr,0,sizeof(client_addr));intclient_st=accept(st,(void*)&client_addr,&len);if(client_st==-1){printf("zhang.pt:acceptfailed%s\n",strerror(errno));break;}else{charsIP[32];memset(sIP,0,sizeof(sIP));sockaddr_toa(&client_addr,sIP);printf(”zhang.pt:acceptby%s\n",sIP);int*tmp=malloc(sizeof(int));*tmp=client_st;pthread_create(&thr_d,&attr,socket_handle,tmp);}}pthread_attr_destroy(&attr);}intmain(intarg,char*args[]){if(arg〈2){printf("zhang.pt:serverporterror!\n”);return0;}intiport=atoi(args[1]);if(iport==0){printf(”zhang。pt:port%disinvalid?。埽睢?,iport);return0;}printf("zhang。pt:serverisbegin*v*!\n");memset(socket_client,0,sizeof(socket_client));intst=socket_creat(yī)e(iport);if(st==0)return0;socket_accept(st);close(st);printf("zhang.pt:serverisend\n");return0;}附錄3(客戶端程序代碼)#include<stdio。h>#include<stdlib。h〉#include〈string。h〉#include<errno.h>#include〈unistd。h〉#include〈arpa/inet.h〉#include<sys/types.h>#include〈sys/socket.h>#include〈pthread.h>#defineBUFSIZE1024void*socket_read(void*arg){intst=*(int*)arg;charbuf[BUFSIZE];while(1){memset(buf,0,sizeof(buf));ssize_trc=recv(st,buf,sizeof(buf),0);if(rc〈=0){printf("zhang。pt:recvfailed,%s\n”,strerror(errno));break;}else{printf(”zhang.pt:recv:%s,recv:%ubyte\n”,buf,rc);}}returnNULL;}void*socket_write(void*arg){intst=*(int*)arg;charbuf[BUFSIZE];while(1){memset(buf,0,sizeof(buf));read(STDIN_FILENO,buf,sizeof(buf));intilen=strlen(buf);if(buf[ilen-1]=='\n'){buf[ilen-1]=0;}ssize_trc=send(st,buf,sizeof(buf),0);printf(”zhang.pt:send:%s,send:%ubyte\n”,buf,rc);if(rc〈=0){printf("zhang.pt:sendfailed,%s\n",strerror(errno));}}returnNULL;}intsocket_connect(constchar*hostname,intiport){intst=socket(AF_INET,SOCK_STREAM,0);structsockaddr_inaddr;memset(&addr,0,sizeof(addr));addr.sin_family=AF_INET;addr。sin_port=htons(iport);addr。sin_addr.s_addr=inet_addr(hostname);if(connect(st,(structsockaddr*)&addr,sizeof(addr))==-1){printf(”zhang。pt:connectfailed%s\n",strerror(errno));}else{printf("zhang。pt:connectsuccess\n”);}returnst;}intmain(intarg,char*args[]){if(arg〈3){printf("zhang.pt:serverip&porterror!\n”);return0;}intiport=at(yī)oi(args[2]);if(iport==0){printf("zhang。pt:port%disinvalid\n”,iport);return0;}printf("zhang。pt:clientisbegin\n");intst=socket_connect(args[1],iport);if(st==0)return0;pthread_tthr_read,thr_write;pthread_create(&thr_read,NULL,socket_read,&st);pthread_create(&thr_write,NULL,socket_write,&st);pthread_join(thr_read,NULL);close(st);printf(”zhang.pt:clientisend\n");return0;}《Linux操作系統(tǒng)》課程設(shè)計報告學院工商學院專業(yè)計算機科學與技術(shù)班級計1341學生姓名:王慢,韓霞,孫潔茹,李強,蔣濤課程設(shè)計任務(wù)書題目基于linux網(wǎng)絡(luò)聊天室的設(shè)計實驗?zāi)康模骸禠inux操作系統(tǒng)課程設(shè)計B》是一門在課程《Linux操作系統(tǒng)與程序設(shè)計B》后獨立開設(shè)的實驗課程。這一門實驗課程的開設(shè)目的是為了通過學生獨立完成一個基于Linux平臺的較大型應(yīng)用程序,鞏固課堂上學到的Linux平臺上的編程規(guī)范、技術(shù)和技巧,培養(yǎng)學生的編寫較大型程序的能力和提高學生綜合應(yīng)用素質(zhì)。本課程設(shè)計實驗主要圍繞Linux平臺上主流的基礎(chǔ)技術(shù)展開,這些技術(shù)包括:Linux的進程、線程通信和同步技術(shù);socket網(wǎng)絡(luò)通信技術(shù)等,這些技術(shù)可以集中體現(xiàn)并應(yīng)用在并發(fā)程序設(shè)計中.通過并發(fā)程序的設(shè)計與開發(fā),培養(yǎng)學生底層軟件開發(fā)的能力,并為將來從事UNIX/Linux平臺開發(fā)、嵌入式開發(fā)等相對高端的軟件開發(fā)工作打下基礎(chǔ)。課程設(shè)計的具體內(nèi)容與要求:閱讀(一個)示例代碼,理解并發(fā)程序設(shè)計并掌握基于Linux平臺并發(fā)程序設(shè)計的方法.在充分理解示例程序的基礎(chǔ)上,重新定義和完善程序的功能,定義數(shù)據(jù)結(jié)構(gòu),劃分程序的功能模塊和接口,明確每個模塊功能以及相互關(guān)系。完成程序的詳細設(shè)計和編碼,并測試。書寫并提交文檔目錄TOC\o”1-3”\h\z\uHYPERLINK\l"_Toc294343043"1引言1HYPERLINK\l"_Toc294343044”1.1課程設(shè)計背景1HYPERLINK\l"_Toc294343045”1.2課程設(shè)計目的2HYPERLINK\l”_Toc294343046”1.3課程設(shè)計內(nèi)容4HYPERLINK\l”_Toc294343047”2技術(shù)介紹7HYPERLINK\l"_Toc294343048"2.1TCP和UDP介紹HYPERLINK\l”_Toc294343049"2.2客戶/服務(wù)器模型HYPERLINK\l"_Toc294343050"2.3網(wǎng)絡(luò)套接字(socket)的概念HYPERLINK\l”_Toc294343051"2。4多線程的概念3系統(tǒng)設(shè)計10HYPERLINK\l"_Toc294343053"3.1系統(tǒng)結(jié)構(gòu)設(shè)計HYPERLINK\l"_Toc294343054”3.2通信模塊設(shè)計4模塊實現(xiàn)124。1系統(tǒng)調(diào)用相關(guān)函數(shù)4.2系統(tǒng)實現(xiàn)過程說明5運行效果15結(jié)束語HYPERLINK\l”_Toc294343061"參考文獻18附錄19-24基于linux網(wǎng)絡(luò)聊天室的設(shè)計摘要本課程設(shè)計主要實現(xiàn)一個Linux下的局域網(wǎng)聊天工具的設(shè)計。該設(shè)計主要分為兩部分,客戶端部分和主機部分。運行服務(wù)器端程序可以和任意運行了客戶端程序的主機進行通信,通信內(nèi)容能夠通過終端顯示出來.兩個部分都使用C語言,利用vi編輯器,通過Berkeley套接口編程實現(xiàn)相關(guān)功能.1引言1。1課程設(shè)計背景Linux是一種針對PC計算機和工作站的操作系統(tǒng),它具有像Windows和Mac那樣的功能齊全的圖形用戶界面(GUI,GraphicalUserInterface)。LinusTorvald和其它的遍布世界各地的編程人員共同開發(fā)的[1].提到Linux我們不能不提GNU和Unix。RichardM.Stallman建立的自由軟件聯(lián)盟出版了兩種許可證,GNU通用公共許可證(GNUGneralPublicLicense,GPL)和GNU函數(shù)庫通用公共許可證(GNULibraryGneralPublicLicense,LGPL)。大部分GNU工程的軟件和文檔是以GNU通用公共許可證發(fā)行的,但是有一些庫是以GNU函數(shù)庫通用公共許可證發(fā)行的.按照GNU通用公共許可證的規(guī)定,Linux的源代碼可以自由獲取,這滿足了我們學習該系統(tǒng)的強烈愿望.GPL充分體現(xiàn)了Stallman的思想:只要用戶所做的修改是同等自由的,用戶可以自由地使用、拷貝、查詢、重用、修改甚至發(fā)布這個軟件。通過這種方式,GPL保證了Linux(以及同一許可證下的大量其他軟件)不僅現(xiàn)在自由可用,而且皮后經(jīng)過任何修改這后都仍然可以自由使用。Unix是由AT-T貝爾實驗室的KenThompson和DennisRitchie于1969年在一臺已經(jīng)廢棄了的PDP—7上開發(fā)的;最初它是一個用匯編語言寫成的單用戶操作系統(tǒng)。后來,他們又在PDP—11上用C語言重新編寫(發(fā)明C語言的部分目的就在于此),把Unix做成為了一個文本處理系統(tǒng),這使Unix在貝爾實驗室得到廣泛的應(yīng)用。Unix的最初版本免費提供給許多知名的大學的計算機系使用。加州大學伯克利分校的計算機系就是其中的一名,并地Unix進行了修改增加了許多新的特點,這就是主為人知的BSC版本的Unix。與此同時,其它獨立開發(fā)的Unix版本也開始萌生。Unix不斷發(fā)展了,各種版本被應(yīng)用到不同的計算機使用。而Linux最初是專門為基于Intel的個人計算機設(shè)計的。(1)Linux的昨天1991年,一名叫LinusTorvalds的芬蘭大學生對Unix各種版本對于80386類的機器的脆弱支持十分不滿,他決定要開發(fā)出一個全功能的、支持POSIX標準的、類Unix的操作系統(tǒng)內(nèi)核,該系統(tǒng)吸收了BSD和SystemV的優(yōu)點,同進摒棄了它們的缺點。他獨立把這個內(nèi)核開發(fā)到0.02版,這個版本已經(jīng)可以運行gcc、bash和很少的一些應(yīng)用程序.后來,他又開始了在因特網(wǎng)上尋求廣泛的幫助。1994年,Linux已經(jīng)升級到1。0版本.它的源代碼量也呈指數(shù)形式增長,實現(xiàn)了基本的TCP/IP功能,此時Linux已經(jīng)擁有大約10萬的用戶。(2)Linux的今天作為一各服務(wù)器級的操作系統(tǒng),Linux已經(jīng)成熟了。現(xiàn)在的Linux內(nèi)核由150多行代碼組成,能作為Web服務(wù)器平臺,也為越來越多的商業(yè)用戶提供文件和打印服務(wù)。它既被當作郵件服務(wù)器的一種候選平臺,也被當作一種強壯而安全的防火墻。Linux的企業(yè)級特性,比如支持多處理器、支持大型文件系統(tǒng)、日志文件系統(tǒng)以及密集型計算和高可用性集群技術(shù),也逐步成熟.桌面上的Linux也在繼續(xù)完善。KDE桌面提供的圖形用戶界面在易用性和可配置方面都能和微軟的Windows相媲美。(3)Linux的明天Linux最強大的生命力在于其公開的開發(fā)過程。每個人都有可以自由獲取內(nèi)核源程序,每個人都有要不得以運載源程序加以修改,而后他人也可以自由獲取你修改后的源程序。Linux這種獨特的自由流暢的開發(fā)模型已被命名為bazaar(集市模型)。Bazaar開發(fā)模型通過重視實驗,征集并充分利用早期的反饋,對巨大數(shù)量的腦力資源進行平衡配置,可以開發(fā)出更優(yōu)秀的軟件。本聯(lián)盟就是想通過bazaar開發(fā)模型,在網(wǎng)上召集一些Linux的愛好者,開發(fā)出更優(yōu)秀的操作系統(tǒng)或軟件.1.2課程設(shè)計目的本課程設(shè)計主要實現(xiàn)一個Linux下的局域網(wǎng)聊天工具的設(shè)計。該設(shè)計主要分為兩部分,客戶端部分和主機部分.運行服務(wù)器端程序可以和任意運行了客戶端程序的主機進行通信,通信內(nèi)容能夠通過終端顯示出來。兩個部分都使用C語言,利用vi編輯器,通過Berkeley套接口編程實現(xiàn)相關(guān)功能.要求:(1)主要實現(xiàn)一個Linux下的局域網(wǎng)聊天工具的設(shè)計,進一步掌握vi,gcc等工具的使用,并且熟悉Linux下的網(wǎng)絡(luò)編程,以及多線程編程。(2)通過實際項目的分析、安裝、配置、測試等工作,掌握用Linux系統(tǒng)下的網(wǎng)絡(luò)聊天室的應(yīng)用.1。3課程設(shè)計內(nèi)容本課程設(shè)計主要實現(xiàn)一個Linux下的局域網(wǎng)聊天工具的設(shè)計。該設(shè)計主要分為兩部分,客戶端部分和主機部分。運行服務(wù)器端程序可以和任意運行了客戶端程序的主機進行通信,通信內(nèi)容能夠通過終端顯示出來.兩個部分都使用C語言,利用vi編輯器,通過Berkeley套接口編程實現(xiàn)相關(guān)功能。2技術(shù)介紹2.1TCP和UDP介紹(1)UDP通信UDP是用戶數(shù)據(jù)報協(xié)議的簡稱。它是以中午連接的邏輯通信信道。UDP在傳送數(shù)據(jù)之前不需要先建立連接,遠地主機的傳輸層在收到udp數(shù)據(jù)報后,不需要給出任何確認,所以不能保證其交付時可靠。它的特點是:因無連接,故提供的是不可靠的信道,但也是因無連接而具有很好的傳輸效率。(2)TCP通信TCP是傳輸控制協(xié)議的簡稱,它是提供一條全雙工的、可靠的信道。TCP提供面向連接的服務(wù),在傳送數(shù)據(jù)之前必須先建立連接,數(shù)據(jù)傳送結(jié)束后要釋放連接.由于TCP要提供可靠的、面向連接的運輸服務(wù),所以不可避免地增加了許多系統(tǒng)開銷,比如確認、流量控制、計時器以及連接管理等都需要占用許多系統(tǒng)的時空資源.兩個計算機之間如果使用TCP通信,其連接過程需要三次握手實現(xiàn),如實驗圖2—1所示。圖2。1用三次握手建立TCP連接對于兩個計算機之間連接的釋放過程也需要類似的3次握手的互相確認的過程,如實驗圖2-2所示。圖2.2TCP連接的釋放過程2.2客戶/服務(wù)器模型在客戶/服務(wù)器模型中,多個相互通信的計算機都作為客戶端,與網(wǎng)絡(luò)服務(wù)器進行連接,并通過服務(wù)器進行信息的傳遞[3]。所以多個客戶端之間的通信就變?yōu)榱丝蛻舳伺c服務(wù)端的通信。所以,采用客戶/服務(wù)器模型進行網(wǎng)絡(luò)聊天需要分別編寫服務(wù)器端和客戶端的程序,服務(wù)器和客戶端之間相互通信的同步關(guān)系和各自的程序流程如實驗圖2-3所示.圖2.3Socket通信流程圖2.3網(wǎng)絡(luò)套接字(socket)的概念Socket接口上TCP/IP網(wǎng)絡(luò)應(yīng)用程序接口(API),它提供了許多函數(shù)和例程,程序員可以使用它們來開發(fā)TCP/IP網(wǎng)絡(luò)應(yīng)用程序.使用Socket接口進行網(wǎng)絡(luò)通信的過程如圖1-3所示,簡要步驟如下:建立一個Socket。按要求配置socket,將socket連接到遠程主機或給socket指定以各本地協(xié)議端口。按要求通過socket發(fā)送和接受數(shù)據(jù)。關(guān)閉此socket.這是通過Socket實現(xiàn)點對點通信需要掌握的4個編程要點。2。4多線程的概念上述點對點通信的實現(xiàn)知識完成了主機進程與服務(wù)器進程之間的連接,建立連接的進程之間是一對一的聯(lián)系,即主機的一個進程與服務(wù)器的一個進程之間建立的連接。而每個進程進行通信的環(huán)節(jié)都包括了發(fā)送信息和接口信息兩個任務(wù),這兩個任務(wù)通過一個端口地址發(fā)送和接收。對于多個并發(fā)的任務(wù)需要創(chuàng)建多個線程或線程去實現(xiàn)。使用一個進程去完成發(fā)送信息是沒有問題的,因為發(fā)送總是主動的;而使用同一個進程再去完成接受信息去不一定會成功,因為接受信息是被動的,所以當沒有信息可以接收時,該進程就會被阻塞,從而導(dǎo)致發(fā)送任務(wù)也一起被阻塞.同一個端口的發(fā)送和接收是兩個并發(fā)任務(wù),應(yīng)該由兩個不同的任務(wù)去分別完成信息的發(fā)送和接收.這樣,當接收信息任務(wù)因沒有信息而被阻塞時,不至于影響發(fā)送任務(wù)的執(zhí)行。那么,發(fā)送和接收兩個任務(wù)是使用兩個進程還是兩個進程去完成呢?在網(wǎng)絡(luò)通信中,端口地址是以進程為單位進程分配的,而一個進程與外界的消息發(fā)送與接收必須通過分配給它的同一個端口進行.因此,不能通過創(chuàng)建進程方式來解決上訴問題,因為兩個進程會分別對應(yīng)兩個不同的端口,而發(fā)送和接收必須使用同一端口。線程不是資源分配的單位,所以如果使用兩個線程不會對線程分配新的端口。因此,本實驗需要使用兩個線程去分別完成發(fā)送和接收信息的任務(wù),這兩個線程共享其進程擁有的統(tǒng)一個端口地址。由于創(chuàng)建進程的進程本身會作為一個線程來調(diào)度,所以只需要再創(chuàng)建一個線程專門負責接收信息就可以了。因此,對于從每個客戶端發(fā)來的請求,服務(wù)器端都要創(chuàng)建相應(yīng)的線程去接收并處理;同理,對于客戶端而言,也要創(chuàng)建一個線程去讀取服務(wù)器端發(fā)來的信息。3系統(tǒng)設(shè)計3.1系統(tǒng)結(jié)構(gòu)設(shè)計本系統(tǒng)采用客戶/服務(wù)器模型,在TCP/IP網(wǎng)絡(luò)應(yīng)用中,通信的兩個進程間相互作用的主要模式是客戶/服務(wù)器模式(Client/Server

model),即客戶向服務(wù)器發(fā)出服務(wù)請求,服務(wù)器接收到請求后,提供相應(yīng)的服務(wù)??蛻?服務(wù)器模式的建立基于以下兩點:首先,建立網(wǎng)絡(luò)的起因是網(wǎng)絡(luò)中軟硬件資源、運算能力和信息不均等,需要共享,從而造就擁有眾多資源的主機提供服務(wù),資源較少的客戶請求服務(wù)這一非對等作用.其次,網(wǎng)間進程通信完全是異步的,相互通信的進程間既不存在父子關(guān)系,又不共享內(nèi)存緩沖區(qū),因此需要一種機制為希望通信的進程間建立聯(lián)系,為二者的數(shù)據(jù)交換提供同步,這就是客戶端/服務(wù)器模式的TCP/IP。在客戶/服務(wù)器模型中,多個相互通信的計算機都作為客戶端,與網(wǎng)絡(luò)服務(wù)器進行連接,并通過服務(wù)器進行信息的傳遞[4]。所以多個客戶端之間的通信就變?yōu)榱丝蛻舳伺c服務(wù)端的通信。服務(wù)器端和客戶端的主要組成如下:服務(wù)器端:套接字創(chuàng)建函數(shù)Socket(),端口綁定函數(shù)Bind(),套接口監(jiān)聽函數(shù)Listen(),接受連接函數(shù)Accept(),數(shù)據(jù)收發(fā)函數(shù)Read()和Write(),以及套接口關(guān)閉函數(shù)Close()??蛻舳耍禾捉涌趧?chuàng)建函數(shù)Socket(),套接口連接函數(shù)Connect(),數(shù)據(jù)收發(fā)函數(shù)Read()和Write(),以及套接口關(guān)閉函數(shù)Close().3.2通信設(shè)計首先運行服務(wù)器端程序,通過Socket()函數(shù)會建立一個套接字,然后通過Bind()函數(shù)綁定一個端口,然后調(diào)用Listen()在套接字指定的端口上開始傾聽,利用Accept()從完全建立連接的隊列中接受一個連接,連接獲得后使用Read()和Write()函數(shù)進行通信。通信結(jié)束后調(diào)用Close()關(guān)閉套接字描述符.運行客戶端的程序,調(diào)用Socket()函數(shù)建立一個套接字,使用Connect()函數(shù)與服務(wù)器端進行連接,連接完成后,使用Write()和Read()與服務(wù)器端進行通信,通信結(jié)束后調(diào)用close()關(guān)閉套接字描述符。4系統(tǒng)實現(xiàn)4.1系統(tǒng)調(diào)用相關(guān)函數(shù)(1)Socket()作用:socket函數(shù)為客戶機或服務(wù)器創(chuàng)建一個sokcet格式:intsocket(intfamily,inttype,intprotocol);參數(shù)說明:Family:表示地址族,可以去AF_UNLX和AF_INT.其中,AF_UNLX只能夠用于單一的UNIX系統(tǒng)進程間通信;AF_INT是針對Internet的,因而可以允許在遠程主機之間通信,實驗中使用AF_INT。Type:網(wǎng)絡(luò)程序所采用的通信協(xié)議,可以取SOCK_STREAM或SOCK_DGRAM。其中,SOCK_STREAM表明使用的是TCP協(xié)議,這樣提供按順序、可靠、雙向、面向連接的比特流;SOCKE_DGRAM表明使用的是UDP協(xié)議,這樣只會提供定長、不可靠、無連接的通信。(2)bind()格式:intbind(intsockfd,structsockaddr*addr,intaddrlen);參數(shù)說明:Sockfd:socket的文件描述符號。Sockaddr:表示名字所用的一個數(shù)據(jù)結(jié)構(gòu),用來保存地址(包括IP地址和端口)Addrlen:設(shè)置結(jié)構(gòu)大小長度。(3)listen()格式:intlisten(intsockfd,intbacklog);作用:監(jiān)聽連接信號,和accepted函數(shù)合同。參數(shù)說明:Sockfd:表示socket調(diào)用返回的文件描述

溫馨提示

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

評論

0/150

提交評論