網絡編程課程設計報告--基于linux網絡聊天室設計_第1頁
已閱讀1頁,還剩19頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、<p>  基于linux網絡聊天室設計</p><p>  摘要:本課程設計是在Linux環(huán)境下基于Socket進行開發(fā)的。系統(tǒng)服務器端和客戶端組成。服務端程序通過共享存儲區(qū)存儲聊天數據,并發(fā)送給每個連接的客戶端。通過多路復用的子進程實現服務端與多個客戶端之間的數據發(fā)送與接收??梢栽趩螜C上開辟兩個窗口分別運行客戶、服務器的程序。本方案經gcc調試器調試成功,可以在機網絡聊天中使用。 </p>

2、;<p>  關鍵詞:網絡聊天;linux ;socket</p><p>  1.linux中socket的基本應用: </p><p>  1.1服務端建立套接字的大致步驟:</p><p>  (1)建立socket。 </p><p>  (2)bindPort 綁定特定的端口。 </p><p&g

3、t;  (3)listen 監(jiān)聽特定的端口。 </p><p>  (4)accept,當有客戶端連接服務器端口時,accept接收信息,并返回新的套接字描述符,提供給操作 </p><p>  (5)根據實際需求,write,read,send,recv等操作 </p><p>  (6)關閉套接字。 </p><p>  1.2客戶端

4、大致步驟: </p><p>  (1)創(chuàng)建socket. </p><p>  (2)根據服務器地址,connect連接到特定服務器。 </p><p>  (3)write,read等讀寫操作。 </p><p>  (4)關閉套接字。 </p><p>  1.3 客戶/服務器模型 </p>

5、<p>  應用程序之間為了能順利地進行通信,一方通常需要處于守候狀態(tài),等待另一方請求的到來。在分布式計算中,一個應用程序被動地等待,而另一個應用程序通過請求啟動通信的模式就是客戶/服務器模式。 客戶/服務器模型的典型運行過程包括五個主要步驟: </p><p>  (1)服務器監(jiān)聽相應窗口的輸入。</p><p>  (2)客戶機發(fā)出請求。 </p><p

6、>  (3)服務器接收到此請求。 </p><p>  (4)服務器處理此請求,并將結果返回給客戶機。 </p><p>  (5)重復上述過程,直至完成一次會話過程任務。</p><p><b>  2.系統(tǒng)結構設計</b></p><p>  2.1 系統(tǒng)結構設計</p><p>  

7、本系統(tǒng)采用客戶/服務器模型,在TCP/IP網絡應用中,通信的兩個進程間相互作用的主要模式是客戶/服務器模式(Client/Server model),即客戶向服務器發(fā)出服務請求,服務器接收到請求后,提供相應的服務。客戶/服務器模式的建立基于以下兩點:首先,建立網絡的起因是網絡中軟硬件資源、運算能力和信息不均等,需要共享,從而造就擁有眾多資源的主機提供服務,資源較少的客戶請求服務這一非對等作用。其次,網間進程通信完全是異步的,相互通信的進

8、程間既不存在父子關系,又不共享內存緩沖區(qū),因此需要一種機制為希望通信的進程間建立聯系,為二者的數據交換提供同步,這就是客戶端/服務器模式的TCP/IP。在客戶/服務器模型中,多個相互通信的計算機都作為客戶端,與網絡服務器進行連接,并通過服務器進行信息的傳遞[4]。所以多個客戶端之間的通信就變?yōu)榱丝蛻舳伺c服務端的通信。</p><p>  服務器端和客戶端的主要組成如下:</p><p> 

9、 服務器端:套接字創(chuàng)建函數Socket(),端口綁定函數Bind(),套接口監(jiān)聽函數Listen(),接受連接函數Accept(),數據收發(fā)函數Read()和Write(),以及套接口關閉函數Close()。</p><p>  客戶端:套接口創(chuàng)建函數Socket(),套接口連接函數Connect(),數據收發(fā)函數Read()和Write(),以及套接口關閉函數Close()。</p><p&

10、gt;<b>  2.2通信設計</b></p><p>  首先運行服務器端程序,通過Socket()函數會建立一個套接字,然后通過Bind()函數綁定一個端口,然后調用Listen()在套接字指定的端口上開始傾聽,利用Accept()從完全建立連接的隊列中接受一個連接,連接獲得后使用Read()和Write()函數進行通信。通信結束后調用Close()關閉套接字描述符。</p>

11、;<p>  運行客戶端的程序,調用Socket()函數建立一個套接字,使用Connect()函數與服務器端進行連接,連接完成后,使用Write()和Read()與服務器端進行通信,通信結束后調用close()關閉套接字描述符。</p><p>  3.1系統(tǒng)調用相關函數</p><p>  (1)Socket()</p><p>  作用:socke

12、t函數為客戶機或服務器創(chuàng)建一個sokcet</p><p><b>  格式:</b></p><p>  int socket(int family,int type,int protocol);</p><p><b>  參數說明:</b></p><p>  Family:表示地址族,可以去

13、AF_UNLX和AF_INT。</p><p>  其中,AF_UNLX只能夠用于單一的UNIX系統(tǒng)進程間通信;AF_INT是針對Internet的,因而可以允許在遠程主機之間通信,實驗中使用AF_INT。</p><p>  Type:網絡程序所采用的通信協(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>  參數說明:</b></p><p>  Sockfd:socket的文件描述符號。</p><p>  Sockaddr:表示名字所用的一個數據結構,用來保存地址(包括IP地址和端口)</p><p>  Addrlen:設置結構大小長度。</p><p>  (3)listen()&l

16、t;/p><p><b>  格式:</b></p><p>  int listen(int sockfd, int backlog);</p><p>  作用:監(jiān)聽連接信號,和accepted函數合同。</p><p><b>  參數說明:</b></p><p>  S

17、ockfd:表示socket調用返回的文件描述符。</p><p>  Backlog:表示接入隊列允許的連接數目,大多數系統(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函數合用,監(jiān)聽信息、接收客戶端請求。</p><p><b>  參數說明:</b></p><p>  Sockfd:表示socket的文件描述符。</p><p>  Addr:表示指向局部的數據結構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)中客戶及連接服務器時使用,connect必須在bind后使用。</p><p><b>  參數作用: </b></p><p>  Sockfd:表示socket的文件描述符。</p><p>  Serv-addr:表示村訪目的端口和ip地址(套接字)的數據結構。</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、數據報socket內部之間的通信。</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;  參數說明:</b></p><p>  How的值為下面一種:</p><p>  0----不允許繼續(xù)接收;</p><p>  1----不允許繼續(xù)發(fā)送;</p><p>  2---不允許繼續(xù)發(fā)送和接收。</p><p>  (8)有關線程的系統(tǒng)調用函數pthread_create()、pth

25、read_join()</p><p><b>  3.2實現過程</b></p><p><b>  (1)監(jiān)聽連接</b></p><p>  利用socket、bind、listen建立連接,步驟是:</p><p>  1) 先用socket函數初始化socket,創(chuàng)建新的sockfd。

26、</p><p>  Sockfd = socket(AF_INT,SOCK_STREAM,0)</p><p>  2)此步驟涉及到IP地址及其處理過程。</p><p><b>  參數說明:</b></p><p>  inet_addr 函數 INADDR_ANY</p><p>  該

27、函數把由小數點分開的十進制IP地址轉為unsinged long 類型,而在實驗中所使用的為INADDR_ANY,使用利用自已的IP地址自動填充。</p><p>  1)利用bind函數綁定端口和IP地址。</p><p>  My_addr.sin_family=AF_INET; /*將地址族類型設定好 */</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函數將自己的IP地址等信息發(fā)送到主機,等待主機調用accept函數來接受請求。</p><p>  (3)主機接收請求,進行數據通信</p><p>  1)主機利用accept接收請求。</p><p>  2)創(chuàng)建子進程,顯示歡迎信息;</p><p&

31、gt;  3)接收返回信息,顯示連接成功,并推出連接;</p><p>  4)關閉客戶端口socket;</p><p>  5)關閉服務端socket,結束子線程。</p><p><b>  4.運行結果</b></p><p>  (1)在編寫完TCP服務端程序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,輸入服務器的IP地址,并檢查器結果的正確性。</p><p>  輸入:【主】# ./server</p><p>  【從】# ./client 127.0.0.1</p><p>  輸出:【主】#server:got connection from 127.0.0.1</p><p>  (5)客戶端、服務器端窗口之間以及

34、交錯發(fā)送信息的方式相互發(fā)送和接收信息。</p><p>  1)客戶端、服務器端窗皆通過鍵盤輸入消息內容平回車,以發(fā)送消息給對方;</p><p>  2)消息中若使用空格,則作為本條消息結束及下一條消息的開始;</p><p>  3)輸入exit則推出運行。</p><p>  開始運行后,服務器端窗口的執(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結束。</p><p>  開始運行后,客戶端窗口的執(zhí)行順序為:</p><p>  接收服務器端發(fā)來的消息“This is server”,如圖(3)所示。</p><p><b>  圖(3)</b></p><p>  發(fā)送消息“This is client”給服務器端如圖(4)所示。</p&

37、gt;<p><b>  圖(4)</b></p><p>  3)鍵入exit結束。</p><p>  上述運行結果表明,客戶端與服務器端之間傳遞的消息已被對方成功接收。</p><p><b>  5.總結</b></p><p>  通過本次課程設計對Linux網絡聊天室的設

38、計,確實積累和總結了不少的經驗,鍛煉了我的獨立工作和實際動手能力,加深了對計算機網絡中socket工作原理及其相互聯系的認識,提高了對復雜的綜合性實踐環(huán)節(jié)具有分析問題、解決問題、概括總結的實際工作能力,對網絡編程項目的開發(fā)、設計過程有初步認識。</p><p>  服務端源程序清單如下,文件名為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函數合用,監(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)中客戶及連接服務器時使用*/</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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論