Linux網(wǎng)絡編程之高級并發(fā)服務器_第1頁
Linux網(wǎng)絡編程之高級并發(fā)服務器_第2頁
Linux網(wǎng)絡編程之高級并發(fā)服務器_第3頁
Linux網(wǎng)絡編程之高級并發(fā)服務器_第4頁
Linux網(wǎng)絡編程之高級并發(fā)服務器_第5頁
已閱讀5頁,還剩10頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、1. 介紹在上一節(jié),我們介紹了Linux簡單的并發(fā)服務器,通過在服務器端建立多個子進程,來接收客戶端的請求,實現(xiàn)并發(fā)處理,但這種方式明顯有缺陷,服務器并不知道客戶端請求的數(shù)量,所以事先建立的進程數(shù)不好確定。所以,這里介紹三種高級并發(fā)服務器模式。第一種是服務器端統(tǒng)一accept,接收客戶端的到來,然后為每個客戶端分配一個進程去處理. 第二種是統(tǒng)一accept接收請求,然后為每個客戶端分配一個線程去處理。第三種建立多個線程去處理客戶端請求,每個線程獨自監(jiān)聽客戶端的請求。顯然,第一種方案解決了簡單服務器的并發(fā)問題。第二種方案其實是對第一種方案的改進,因為線程切換的開銷明顯要小于進程切換的開銷。第三種

2、方案就是原來用進程去處理每個請求,現(xiàn)在換成用線程去處理,個人認為改進不是很大.2. 高級并發(fā)服務器算法流程(1)統(tǒng)一accept,多進程  socket(.);  bind(.);  listen(.);  while(1)  accept(.);  fork(.);/子進程  close(.);/關閉服務器套接字子進程: recv(.); process(.); send(.); close(.);/關閉客戶端(2)統(tǒng)一accept,多線程  socket(.);

3、  bind(.);  listen(.);  while(1)  accept(.);  pthread_create(.);   close(.);/關閉服務器線程1:recv(.);process(.);send(.);close(.);/關閉客戶端(3)accept放入每個線程 socket(.); bind(.); listen(.);pthread_create(.);pthread_join(.);/等待線程結束close(.);/關閉服務器線程1:Mutex_lock/互斥鎖ac

4、cept(.);Mutex_unlock(.);recv(.);process(.);send(.);close(.);/客戶端3. 相關例子TCP服務器:(1)統(tǒng)一accept多進程服務器;#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <time.h>/*高級并發(fā)服務器TCP統(tǒng)一accept當

5、有客戶端到來時,為每個客戶端建立進程,然后每個進程處理客戶端的請求,動態(tài)的建立進程*/#define PORT 8888#define BUFFERSIZE 1024#define BACKLOG 2static void handle(int sc)/處理客戶端的請求  char bufferBUFFERSIZE;  time_t now;  int size;  memset(buffer,0,BUFFERSIZE);   size=recv(sc,buffer,BUFFERSIZE,0);  if(size>0&

6、amp;&!strncmp(buffer,"TIME",4)/時間服務器,當客戶端請求時間就把時間發(fā)送給客戶端      memset(buffer,0,BUFFERSIZE);      now=time(NULL);      sprintf(buffer,"%24srn",ctime(&now);     send(sc,buffer,strle

7、n(buffer),0); close(sc);int main(int argc,char*argv)  int ret;  int s;  int sc;/用于服務器與客戶端進行數(shù)據(jù)傳輸?shù)奶捉幼?#160; struct sockaddr_in server_addr;  struct sockaddr_in client_addr;  int len;  len=sizeof(client_addr);  /建立流式套接字  s=socket(AF_INET,SOCK_STREAM,0); 

8、; if(s<0)    perror("socket error");   return -1;   /將地址結構綁定到套接字描述符上去 memset(&server_addr,0,sizeof(server_addr); server_addr.sin_family=AF_INET; server_addr.sin_port=htons(PORT); server_addr.sin_addr.s_addr=htonl(INADDR_ANY);

9、60;ret=bind(s,(struct sockaddr*)&server_addr,sizeof(server_addr); if(ret=-1)   perror("bind error");   return -1; ret=listen(s,BACKLOG);if(ret<0)   perror("listen error");  return -1; while(1)   sc=accept(s,(struc

10、t sockaddr*)&client_addr,&len);  if(sc<0)    continue;    if(fork()=0)/子進程  handle(sc);  close(s);/子進程關閉用于監(jiān)聽的套接字  else    close(sc);/父進程關閉客戶端套接字 客戶端:#include <stdio.h>#include <string.h>#include <stdlib.h>#

11、include <sys/socket.h>#include <sys/types.h>#include <time.h>#include <netinet/in.h>#define PORT 8888#define BUFFERSIZE 1024int main(int argc,char*argv) int s; int ret; int size; struct sockaddr_in server_addr; char bufferBUFFERSIZE; s=socket(AF_

12、INET,SOCK_STREAM,0); if(s<0)  perror("socket error");  return -1;bzero(&server_addr,sizeof(server_addr);/將地址結構綁定到套接字server_addr.sin_family=AF_INET;server_addr.sin_port=htons(PORT);server_addr.sin_addr.s_addr=htonl(INADDR_ANY);/連接服務器 ret=connect(s,(struct sockaddr

13、*)&server_addr,sizeof(server_addr); if(ret=-1)  perror("connect error");  return -1;memset(buffer,0,BUFFERSIZE);strcpy(buffer,"TIME");size=send(s,buffer,strlen(buffer),0);if(size<0)  perror("send error");  return -1;memset(buffer,0,BUFFER

14、SIZE);size=recv(s,buffer,BUFFERSIZE,0);if(size<0)  perror("recv error");  return;printf("%s",buffer);close(s);return 0;(2)統(tǒng)一accept多線程服務器:#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/types.h>

15、;#include <netinet/in.h>#include <time.h>/*TCP并發(fā)服務器,采用多線程,每次客戶端發(fā)送請求,主線程建立一個子線程,用于處理客戶端的請求線程具有速度快,占用資源少,數(shù)據(jù)可以共享等優(yōu)點 統(tǒng)一accept*/#define PORT 8888#define BUFFERSIZE 1024#define BACKLOG 2static void handle(void* sc1) int sc; time_t now; char bufferBUFFERSIZE;  int size; 

16、; sc=*(int*)sc1);/轉(zhuǎn)換成int指針,然后取值,sc1本身就是一個指針 memset(buffer,0,BUFFERSIZE); size=recv(sc,buffer,BUFFERSIZE,0); if(size>0&&!strncmp(buffer,"TIME",4)/請求服務器的時間     memset(buffer,0,BUFFERSIZE);/清0   now=time(NULL);    sprintf(buffe

17、r,"%24srn",ctime(&now);    send(sc,buffer,strlen(buffer),0);/向客戶端發(fā)送數(shù)據(jù)close(sc);/關閉客戶端int main(int argc,char*argv)  int ret;  int s;  int sc;  int len;  pthread_t thread1;/定義線程名   struct sockaddr_in server_addr,client_addr;  len=siz

18、eof(client_addr);  /建立流式套接字  s=socket(AF_INET,SOCK_STREAM,0);  if(s<0)    perror("socket error");    return -1;    /將服務器端的地址結構綁定到套接字描述符  server_addr.sin_family=AF_INET;  server_addr.sin_addr.s_addr=htonl(INADDR_ANY); 

19、 server_addr.sin_port=htons(PORT);  ret=bind(s,(struct sockaddr*)&server_addr,sizeof(struct sockaddr_in);  if(ret<0)    perror("bind error");    return -1;  /監(jiān)聽  ret=listen(s,BACKLOG);  if(ret<0)    perror(&quo

20、t;listen error");    return -1;  /接收客戶端的請求for(;)    sc=accept(s,(struct sockaddr*)&client_addr,&len);    if(sc<0)     continue;    else    pthread_create(&thread1,NULL,handle,(void*)&am

21、p;sc);/建立線程,讓線程去處理,最后一個字段是傳遞給線程處理函數(shù)handle的參數(shù)   close(s);客戶端:#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/types.h>#include <time.h>#include <netinet/in.h>#define PORT 8888#define BUFFERSIZE 1024int mai

22、n(int argc,char*argv) int s; int ret; int size; struct sockaddr_in server_addr; char bufferBUFFERSIZE; s=socket(AF_INET,SOCK_STREAM,0); if(s<0)  perror("socket error");  return -1;bzero(&server_addr,sizeof(server_addr);/將地址結構綁定到套接字server_

23、addr.sin_family=AF_INET;server_addr.sin_port=htons(PORT);server_addr.sin_addr.s_addr=htonl(INADDR_ANY);/連接服務器 ret=connect(s,(struct sockaddr*)&server_addr,sizeof(server_addr); if(ret=-1)  perror("connect error");  return -1;memset(buffer,0,BUFFERSIZE);strcpy(buffer,

24、"TIME");size=send(s,buffer,strlen(buffer),0);if(size<0)  perror("send error");  return -1;memset(buffer,0,BUFFERSIZE);size=recv(s,buffer,BUFFERSIZE,0);if(size<0)  perror("recv error");  return;printf("%s",buffer);close(s);return 0;(3)

25、單獨線程accept服務器:#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <time.h>#include <pthread.h>/*多線程TCP并發(fā)服務器主線程創(chuàng)建多個線程,然后每個線程獨立的accept和進行數(shù)據(jù)的發(fā)送與接收多線程,獨立accept*/#define PORT 8

26、888#define BUFFERSIZE 1024#define BACKLOG 2#define CLIENTNUM 3static void *handle(void* s1) int s; int len; int sc; pthread_mutex_t alock=PTHREAD_MUTEX_INITIALIZER; char bufferBUFFERSIZE; int size; struct sockaddr_in client_addr; s=*(int*)s1);/得到服務器端的套接字描述符/等待

27、客戶端連接 len=sizeof(client_addr); for(;)/不停的循環(huán)等待客戶端的連接   time_t now;   /進入互斥區(qū),每次一個線程處理客戶端pthread_mutex_lock(&alock);  sc=accept(s,(struct sockaddr*)&client_addr,&len);pthread_mutex_unlock(&alock);memset(buffer,0,BUFFERSIZE);size=recv(sc,buffer,BUFFERSI

28、ZE,0);if(size>0&&!strncmp(buffer,"TIME",4)  memset(buffer,0,BUFFERSIZE);  now=time(NULL);  sprintf(buffer,"%24srn",ctime(&now);  send(sc,buffer,strlen(buffer),0);close(sc);/關閉客戶端 int main(int argc,char*argv)   int ret;   int

29、s;   int len;   int i;   pthread_t threadCLIENTNUM;   struct sockaddr_in server_addr;   /建立流式套接字   s=socket(AF_INET,SOCK_STREAM,0);   if(s<0)    perror("socket error");    return -1; 

30、;  /將地址結構綁定到套接字上  server_addr.sin_family=AF_INET;  server_addr.sin_addr.s_addr=htonl(INADDR_ANY);  server_addr.sin_port=htons(PORT);  ret=bind(s,(struct sockaddr*)&server_addr,sizeof(struct sockaddr_in);  if(ret=-1)   perror("bind error"); &

31、#160; return -1;  /監(jiān)聽  ret=listen(s,BACKLOG);  if(ret=-1)    perror("listen error");     return -1; /建立3個線程,每個線程獨立的accept  for(i=0;i<CLIENTNUM;i+)    pthread_create(&threadi,NULL,handle,(void*)&s);/線程的處理函

32、數(shù)為handle,傳遞的參數(shù)為套接字描述符s      /while(1);/等待線程結束 for(i=0;i<CLIENTNUM;i+)   pthread_join(threadi,NULL);  /關閉套接字close(s);return 0;客戶端:#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/types.h>#include <time.h>#include <netinet/in.h>#define PORT 8888#define BUFFERSIZE 1024int main(int argc,char*a

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論