版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、<p> 基于linux網(wǎng)絡(luò)聊天室設(shè)計</p><p> 摘要:本課程設(shè)計是在Linux環(huán)境下基于Socket進行開發(fā)的。系統(tǒng)服務(wù)器端和客戶端組成。服務(wù)端程序通過共享存儲區(qū)存儲聊天數(shù)據(jù),并發(fā)送給每個連接的客戶端。通過多路復(fù)用的子進程實現(xiàn)服務(wù)端與多個客戶端之間的數(shù)據(jù)發(fā)送與接收??梢栽趩螜C上開辟兩個窗口分別運行客戶、服務(wù)器的程序。本方案經(jīng)gcc調(diào)試器調(diào)試成功,可以在機網(wǎng)絡(luò)聊天中使用。 </p>
2、;<p> 關(guān)鍵詞:網(wǎng)絡(luò)聊天;linux ;socket</p><p> 1.linux中socket的基本應(yīng)用: </p><p> 1.1服務(wù)端建立套接字的大致步驟:</p><p> (1)建立socket。 </p><p> (2)bindPort 綁定特定的端口。 </p><p&g
3、t; (3)listen 監(jiān)聽特定的端口。 </p><p> (4)accept,當有客戶端連接服務(wù)器端口時,accept接收信息,并返回新的套接字描述符,提供給操作 </p><p> (5)根據(jù)實際需求,write,read,send,recv等操作 </p><p> (6)關(guān)閉套接字。 </p><p> 1.2客戶端
4、大致步驟: </p><p> (1)創(chuàng)建socket. </p><p> (2)根據(jù)服務(wù)器地址,connect連接到特定服務(wù)器。 </p><p> (3)write,read等讀寫操作。 </p><p> (4)關(guān)閉套接字。 </p><p> 1.3 客戶/服務(wù)器模型 </p>
5、<p> 應(yīng)用程序之間為了能順利地進行通信,一方通常需要處于守候狀態(tài),等待另一方請求的到來。在分布式計算中,一個應(yīng)用程序被動地等待,而另一個應(yīng)用程序通過請求啟動通信的模式就是客戶/服務(wù)器模式。 客戶/服務(wù)器模型的典型運行過程包括五個主要步驟: </p><p> (1)服務(wù)器監(jiān)聽相應(yīng)窗口的輸入。</p><p> (2)客戶機發(fā)出請求。 </p><p
6、> (3)服務(wù)器接收到此請求。 </p><p> (4)服務(wù)器處理此請求,并將結(jié)果返回給客戶機。 </p><p> (5)重復(fù)上述過程,直至完成一次會話過程任務(wù)。</p><p><b> 2.系統(tǒng)結(jié)構(gòu)設(shè)計</b></p><p> 2.1 系統(tǒng)結(jié)構(gòu)設(shè)計</p><p>
7、本系統(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)間進程通信完全是異步的,相互通信的進
8、程間既不存在父子關(guān)系,又不共享內(nèi)存緩沖區(qū),因此需要一種機制為希望通信的進程間建立聯(lián)系,為二者的數(shù)據(jù)交換提供同步,這就是客戶端/服務(wù)器模式的TCP/IP。在客戶/服務(wù)器模型中,多個相互通信的計算機都作為客戶端,與網(wǎng)絡(luò)服務(wù)器進行連接,并通過服務(wù)器進行信息的傳遞[4]。所以多個客戶端之間的通信就變?yōu)榱丝蛻舳伺c服務(wù)端的通信。</p><p> 服務(wù)器端和客戶端的主要組成如下:</p><p>
9、 服務(wù)器端:套接字創(chuàng)建函數(shù)Socket(),端口綁定函數(shù)Bind(),套接口監(jiān)聽函數(shù)Listen(),接受連接函數(shù)Accept(),數(shù)據(jù)收發(fā)函數(shù)Read()和Write(),以及套接口關(guān)閉函數(shù)Close()。</p><p> 客戶端:套接口創(chuàng)建函數(shù)Socket(),套接口連接函數(shù)Connect(),數(shù)據(jù)收發(fā)函數(shù)Read()和Write(),以及套接口關(guān)閉函數(shù)Close()。</p><p&
10、gt;<b> 2.2通信設(shè)計</b></p><p> 首先運行服務(wù)器端程序,通過Socket()函數(shù)會建立一個套接字,然后通過Bind()函數(shù)綁定一個端口,然后調(diào)用Listen()在套接字指定的端口上開始傾聽,利用Accept()從完全建立連接的隊列中接受一個連接,連接獲得后使用Read()和Write()函數(shù)進行通信。通信結(jié)束后調(diào)用Close()關(guān)閉套接字描述符。</p>
11、;<p> 運行客戶端的程序,調(diào)用Socket()函數(shù)建立一個套接字,使用Connect()函數(shù)與服務(wù)器端進行連接,連接完成后,使用Write()和Read()與服務(wù)器端進行通信,通信結(jié)束后調(diào)用close()關(guān)閉套接字描述符。</p><p> 3.1系統(tǒng)調(diào)用相關(guān)函數(shù)</p><p> (1)Socket()</p><p> 作用:socke
12、t函數(shù)為客戶機或服務(wù)器創(chuàng)建一個sokcet</p><p><b> 格式:</b></p><p> int socket(int family,int type,int protocol);</p><p><b> 參數(shù)說明:</b></p><p> Family:表示地址族,可以去
13、AF_UNLX和AF_INT。</p><p> 其中,AF_UNLX只能夠用于單一的UNIX系統(tǒng)進程間通信;AF_INT是針對Internet的,因而可以允許在遠程主機之間通信,實驗中使用AF_INT。</p><p> Type:網(wǎng)絡(luò)程序所采用的通信協(xié)議,可以取SOCK_STREAM或SOCK_DGRAM。其中,SOCK_STREAM表明使用的是TCP協(xié)議,這樣提供按順序、可靠、雙
14、向、面向連接的比特流;SOCKE_DGRAM表明使用的是UDP協(xié)議,這樣只會提供定長、不可靠、無連接的通信。</p><p> (2)bind( )</p><p><b> 格式:</b></p><p> int bind(int sockfd,struct sockaddr *addr,int addrlen);</p>
15、<p><b> 參數(shù)說明:</b></p><p> Sockfd:socket的文件描述符號。</p><p> Sockaddr:表示名字所用的一個數(shù)據(jù)結(jié)構(gòu),用來保存地址(包括IP地址和端口)</p><p> Addrlen:設(shè)置結(jié)構(gòu)大小長度。</p><p> (3)listen()&l
16、t;/p><p><b> 格式:</b></p><p> int listen(int sockfd, int backlog);</p><p> 作用:監(jiān)聽連接信號,和accepted函數(shù)合同。</p><p><b> 參數(shù)說明:</b></p><p> S
17、ockfd:表示socket調(diào)用返回的文件描述符。</p><p> Backlog:表示接入隊列允許的連接數(shù)目,大多數(shù)系統(tǒng)允許20個,也可以子定義5~10個。</p><p> (4)accept()</p><p><b> 格式:</b></p><p> Int accept (int sockfd, v
18、oid *addr, int *addrlen);</p><p> 作用:與listen函數(shù)合用,監(jiān)聽信息、接收客戶端請求。</p><p><b> 參數(shù)說明:</b></p><p> Sockfd:表示socket的文件描述符。</p><p> Addr:表示指向局部的數(shù)據(jù)結(jié)構(gòu)struct sockad
19、dr-in的指針。</p><p> Addrlen:表示地址的長度。</p><p> (5)connect()</p><p><b> 格式:</b></p><p> int connect( int sockfd , struct sockaddr *serv_addr , int addrlen);&
20、lt;/p><p> 作用:在面向連接的系統(tǒng)中客戶及連接服務(wù)器時使用,connect必須在bind后使用。</p><p><b> 參數(shù)作用: </b></p><p> Sockfd:表示socket的文件描述符。</p><p> Serv-addr:表示村訪目的端口和ip地址(套接字)的數(shù)據(jù)結(jié)構(gòu)。</p
21、><p> (6)send() 和 recv()</p><p><b> 格式1:</b></p><p> Int send (int sockfd, const vod *msg,int len, int flags);</p><p><b> 功能:發(fā)送信息。</b></p>
22、;<p><b> 格式2:</b></p><p> Int recv (int sockfd , void *buf,int len, usigned int flags);</p><p> 作用:用于流式socket、數(shù)據(jù)報socket內(nèi)部之間的通信。</p><p> (7)close( ) 和 shutdown
23、 ( )</p><p><b> 格式:</b></p><p> Close( int sockfd)</p><p><b> 或 </b></p><p> Int shutdown(int sockfd , int how);</p><p><b&g
24、t; 參數(shù)說明:</b></p><p> How的值為下面一種:</p><p> 0----不允許繼續(xù)接收;</p><p> 1----不允許繼續(xù)發(fā)送;</p><p> 2---不允許繼續(xù)發(fā)送和接收。</p><p> (8)有關(guān)線程的系統(tǒng)調(diào)用函數(shù)pthread_create()、pth
25、read_join()</p><p><b> 3.2實現(xiàn)過程</b></p><p><b> (1)監(jiān)聽連接</b></p><p> 利用socket、bind、listen建立連接,步驟是:</p><p> 1) 先用socket函數(shù)初始化socket,創(chuàng)建新的sockfd。
26、</p><p> Sockfd = socket(AF_INT,SOCK_STREAM,0)</p><p> 2)此步驟涉及到IP地址及其處理過程。</p><p><b> 參數(shù)說明:</b></p><p> inet_addr 函數(shù) INADDR_ANY</p><p> 該
27、函數(shù)把由小數(shù)點分開的十進制IP地址轉(zhuǎn)為unsinged long 類型,而在實驗中所使用的為INADDR_ANY,使用利用自已的IP地址自動填充。</p><p> 1)利用bind函數(shù)綁定端口和IP地址。</p><p> My_addr.sin_family=AF_INET; /*將地址族類型設(shè)定好 */</p><p> My_addr
28、.sin_port=htons(MYPORT; /* 將端口給其賦值*/</p><p> My_addr.sin_addr.s_addr=INADDR_ANY; /*用連接地址自動填充ip*/</p><p> Bind(sockfd,(stuct sockaddr*)&my_addr,sizeof(stuct sockaddr));</p><
29、;p> /*sockfd 是分配的socket名字,my-addr則便是分配好的端口與IP,用bind綁定*/</p><p> 2)利用listen監(jiān)聽請求</p><p><b> (2) 發(fā)送請求</b></p><p> 1)利用gethostbyname獲取主機信息。</p><p> 2)初
30、始化socket端口。</p><p> 3)利用connect函數(shù)將自己的IP地址等信息發(fā)送到主機,等待主機調(diào)用accept函數(shù)來接受請求。</p><p> (3)主機接收請求,進行數(shù)據(jù)通信</p><p> 1)主機利用accept接收請求。</p><p> 2)創(chuàng)建子進程,顯示歡迎信息;</p><p&
31、gt; 3)接收返回信息,顯示連接成功,并推出連接;</p><p> 4)關(guān)閉客戶端口socket;</p><p> 5)關(guān)閉服務(wù)端socket,結(jié)束子線程。</p><p><b> 4.運行結(jié)果</b></p><p> (1)在編寫完TCP服務(wù)端程序server.c后,用 gcc –lpthread
32、–o server.c server 生成程序server。</p><p> (2)在編寫完TCP客戶端程序client.c后,用gcc –lpthread –o client.c client 生成程序client</p><p> (3)在主機上打開一窗口,運行server。</p><p> (4)再打開另一個窗口或者在另一個主句上打開一個窗口,運行c
33、lient,輸入服務(wù)器的IP地址,并檢查器結(jié)果的正確性。</p><p> 輸入:【主】# ./server</p><p> 【從】# ./client 127.0.0.1</p><p> 輸出:【主】#server:got connection from 127.0.0.1</p><p> (5)客戶端、服務(wù)器端窗口之間以及
34、交錯發(fā)送信息的方式相互發(fā)送和接收信息。</p><p> 1)客戶端、服務(wù)器端窗皆通過鍵盤輸入消息內(nèi)容平回車,以發(fā)送消息給對方;</p><p> 2)消息中若使用空格,則作為本條消息結(jié)束及下一條消息的開始;</p><p> 3)輸入exit則推出運行。</p><p> 開始運行后,服務(wù)器端窗口的執(zhí)行順序為:</p&g
35、t;<p> 鍵入”this is server”發(fā)送給客戶端,如圖(1)所示。</p><p><b> 圖(1)</b></p><p> 接收客戶端發(fā)來的”this is client”,如圖(2)所示。</p><p><b> 圖(2)</b></p><p> 3
36、)輸入exit結(jié)束。</p><p> 開始運行后,客戶端窗口的執(zhí)行順序為:</p><p> 接收服務(wù)器端發(fā)來的消息“This is server”,如圖(3)所示。</p><p><b> 圖(3)</b></p><p> 發(fā)送消息“This is client”給服務(wù)器端如圖(4)所示。</p&
37、gt;<p><b> 圖(4)</b></p><p> 3)鍵入exit結(jié)束。</p><p> 上述運行結(jié)果表明,客戶端與服務(wù)器端之間傳遞的消息已被對方成功接收。</p><p><b> 5.總結(jié)</b></p><p> 通過本次課程設(shè)計對Linux網(wǎng)絡(luò)聊天室的設(shè)
38、計,確實積累和總結(jié)了不少的經(jīng)驗,鍛煉了我的獨立工作和實際動手能力,加深了對計算機網(wǎng)絡(luò)中socket工作原理及其相互聯(lián)系的認識,提高了對復(fù)雜的綜合性實踐環(huán)節(jié)具有分析問題、解決問題、概括總結(jié)的實際工作能力,對網(wǎng)絡(luò)編程項目的開發(fā)、設(shè)計過程有初步認識。</p><p> 服務(wù)端源程序清單如下,文件名為server.c</p><p> #include<stdio.h></p
39、><p> #include<stdlib.h></p><p> #include<errno.h></p><p> #include<string.h></p><p> #include<sys/types.h></p><p> #include<n
40、etinet/in.h></p><p> #include<sys/socket.h></p><p> #include<sys/wait.h></p><p> #include<pthread.h></p><p> #define MYPORT 3490</p><
41、;p> #define BACKLOG 10 </p><p> #define MAXDATASIZE 1024</p><p> int sockfd,new_fd;</p><p> pthread_t accthread,recthread;</p><p> void recmessage(void){</p
42、><p><b> while(1){</b></p><p> int numbytes;</p><p> char buf[MAXDATASIZE];</p><p> if((numbytes = recv(new_fd,buf,MAXDATASIZE,0)) == -1){</p><p
43、> perror("recv");</p><p><b> exit(1);</b></p><p><b> }</b></p><p> buf[numbytes] = '\0';</p><p> if(strcmp(buf,"e
44、xit") == 0){</p><p> printf("Client is closed\n");</p><p> close(new_fd);</p><p> close(sockfd);</p><p><b> exit(1);</b></p><p
45、><b> }</b></p><p> printf("Client:%s\n",buf);</p><p><b> }</b></p><p><b> }</b></p><p> void acceptconnect(void)
46、 / *與listen函數(shù)合用,監(jiān)聽信息、接收客戶端請求*/</p><p><b> {</b></p><p> struct sockaddr_in their_addr;</p><p> int sin_size;</p><p> sin_size = sizeof(struct socka
47、ddr_in);</p><p> if((new_fd = accept(sockfd,(struct sockaddr*)&their_addr,&sin_size)) == -1){</p><p> perror("accept");</p><p><b> exit(1);</b></
48、p><p><b> }</b></p><p> printf("server:got connection from %s\n",inet_ntoa(their_addr.sin_addr));</p><p> if((pthread_create(&recthread,NULL,(void *)recmes
49、sage,NULL))!= 0){</p><p> printf("Create thread error!\r\n");</p><p><b> exit(1);</b></p><p><b> }</b></p><p><b> }</b>
50、;</p><p> int main(void){</p><p> struct sockaddr_in my_addr;</p><p> if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){</p><p> perror("socket");</p&
51、gt;<p><b> exit(1);</b></p><p><b> }</b></p><p> my_addr.sin_family = AF_INET;</p><p> my_addr.sin_port = htons(MYPORT);</p><p> my_
52、addr.sin_addr.s_addr = INADDR_ANY;</p><p> bzero(&(my_addr.sin_zero),8);</p><p> if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr)) == -1){</p><p> perror
53、("bind");</p><p><b> exit(1);</b></p><p><b> }</b></p><p> if(listen(sockfd,BACKLOG) == -1){ /*監(jiān)聽連接信號*/</p><p> perror(&qu
54、ot;listen");</p><p><b> exit(1);</b></p><p><b> }</b></p><p> if((pthread_create(&accthread,NULL,(void *)acceptconnect,NULL)) != 0){</p>&
55、lt;p> printf("Create thread error!\r\n");</p><p><b> exit(1);</b></p><p><b> }</b></p><p><b> while(1){</b></p><p>
56、 char msg[MAXDATASIZE];</p><p> scanf("%s",msg);</p><p> if(send(new_fd,msg,strlen(msg),0) == -1){</p><p> perror("send");</p><p> close(new_fd
57、);</p><p><b> exit(1);</b></p><p><b> }</b></p><p> if(strcmp(msg,"exit") == 0){</p><p> printf("Byebye!\n");</p>
58、<p> close(new_fd);</p><p> close(sockfd);</p><p><b> exit(1);</b></p><p><b> }</b></p><p><b> }</b></p><p>
59、<b> return 0;</b></p><p><b> }</b></p><p> 客戶端源程序清單如下,文件名為client.c</p><p> #include<stdio.h></p><p> #include<stdlib.h></p&g
60、t;<p> #include<errno.h></p><p> #include<string.h></p><p> #include<netdb.h></p><p> #include<sys/types.h></p><p> #include<neti
61、net/in.h></p><p> #include<sys/socket.h></p><p> #include<pthread.h></p><p> #define PORT 3490</p><p> #define MAXDATASIZE 1024</p><p>
62、 int sockfd;</p><p> pthread_t recthread;</p><p> void recmessage(void){</p><p><b> while(1){</b></p><p> int numbytes;</p><p> char buf[M
63、AXDATASIZE];</p><p> if((numbytes = recv(sockfd,buf,MAXDATASIZE,0)) == -1){</p><p> perror("recv");</p><p><b> exit(1);</b></p><p><b> }
64、</b></p><p> buf[numbytes]='\0';</p><p> if(strcmp(buf,"exit") == 0){</p><p> printf("Server is closed\n");</p><p> close(sockfd);
65、</p><p><b> exit(1);</b></p><p><b> }</b></p><p> printf("Server:%s\n",buf);</p><p><b> }</b></p><p><
66、b> }</b></p><p> int main(int argc,char *argv[]){</p><p> struct hostent *he;</p><p> struct sockaddr_in their_addr;</p><p> if(argc != 2){</p><
67、;p> fprintf(stderr,"usage:client hostname\n");</p><p><b> exit(1);</b></p><p><b> }</b></p><p> if((he=gethostbyname(argv[1])) == NULL){<
68、/p><p> herror("gethostbyname");</p><p><b> exit(1);</b></p><p><b> }</b></p><p> if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){
69、</p><p> perror("socket");</p><p><b> exit(1);</b></p><p><b> }</b></p><p> their_addr.sin_family = AF_INET;</p><p>
70、 their_addr.sin_port = htons(PORT);</p><p> their_addr.sin_addr = *((struct in_addr *)he->h_addr);</p><p> bzero(&(their_addr.sin_zero),8);</p><p> if(connect(sockfd,(stru
71、ct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1)</p><p> /*在面向連接的系統(tǒng)中客戶及連接服務(wù)器時使用*/</p><p><b> {</b></p><p> perror("connect");</p><p&
72、gt;<b> exit(1);</b></p><p><b> }</b></p><p> if((pthread_create(&recthread,NULL,(void *)recmessage,NULL))!=0){</p><p> printf("Create thread err
73、or!\r\n");</p><p><b> exit(1);</b></p><p><b> }</b></p><p><b> while(1){</b></p><p> char msg[MAXDATASIZE];</p><
74、;p> scanf("%s",msg);</p><p> if(send(sockfd,msg,strlen(msg),0) == -1){</p><p> perror("send");</p><p> close(sockfd);</p><p><b> exit(
75、1);</b></p><p><b> }</b></p><p> if(strcmp(msg,"exit") == 0){</p><p> printf("Byebye!\n");</p><p> close(sockfd);</p>&
76、lt;p><b> exit(1);</b></p><p><b> }</b></p><p><b> }</b></p><p><b> return 0;</b></p><p><b> }</b><
溫馨提示
- 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. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 網(wǎng)絡(luò)編程課程設(shè)計---網(wǎng)絡(luò)聊天室
- 網(wǎng)絡(luò)編程課程設(shè)計-java聊天室
- 網(wǎng)絡(luò)編程課程設(shè)計報告-android_socket_聊天室
- java網(wǎng)絡(luò)聊天室課程設(shè)計
- tcp課程設(shè)計--網(wǎng)絡(luò)聊天室
- 軟件課程設(shè)計報告---簡易網(wǎng)絡(luò)聊天室
- 網(wǎng)絡(luò)編程課程設(shè)計-簡單的聊天室程序設(shè)計
- 網(wǎng)絡(luò)編程課程設(shè)計-簡單的聊天室程序設(shè)計
- 計算機網(wǎng)絡(luò)課程設(shè)計--基于tcp協(xié)議編程的網(wǎng)絡(luò)聊天室
- 基于java網(wǎng)絡(luò)聊天室設(shè)計
- java網(wǎng)絡(luò)聊天室畢業(yè)課程設(shè)計報告(內(nèi)附代碼)
- socket網(wǎng)絡(luò)編程linux下實現(xiàn)聊天室費下載
- 基于linux的socket網(wǎng)絡(luò)編程聊天工具課程設(shè)計
- 基于java的簡單網(wǎng)絡(luò)聊天室編程
- 計算機網(wǎng)絡(luò)課程設(shè)計--聊天室
- jsp課程設(shè)計報告--在線聊天室
- 《web開發(fā)》課程設(shè)計報告--聊天室
- web課程設(shè)計—— 聊天室
- mfc課程設(shè)計報告---聊天室程序設(shè)計
- java課程設(shè)計--聊天室系統(tǒng)
評論
0/150
提交評論