文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>第七篇 Linux的高级应用编程-网络编程中并发服务..

第七篇 Linux的高级应用编程-网络编程中并发服务..

时间:2009-07-12  来源:embededgood

并发服务器有三种设计模式: 多进程:每个进程服务一个客户端。优势是有各自独立的地址空间,可靠性高,但进程调度开销大,无法资源共享,进程间通信机制复杂。 多线程:每个线程服务一个客户端。优势是开销小,通信机制简单,可共享内存。但共享地址空间,可靠性低,一个服务器出现问题时可能导致系统崩溃,同时全局共享可能带来竞争,共享资源需要互斥,对编程要求高。 单进程:占有的进程及线程资源少,通信机制简单。但监听服务器及各个子服务器揉和在一起,程序结构复杂不清晰,编程麻烦。     1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 // File: mult-pr-tcp-server.c
/* 多进程并发服务器。该程序等候客户连接,一旦连接则显示客户的地址, 接着接收该客户的名字并显示。然后接收来自该客户的信息(字符串)。 每当收到一个字符串,则显示该字符串,并将字符串反转,再将反转的字 符发回客户。之后,继续等待接收该客户的信息直至该客户关闭连接。服 务器具有同时处理多客户的能力。 */ #include <stdio.h>          /* These are the usual header files */ #include <strings.h>          /* for bzero() */ #include <unistd.h>         /* for close() */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>   #define PORT 1234   /* Port that will be opened */ #define BACKLOG 2   /* Number of allowed connections */ #define MAXDATASIZE 1000  void process_cli(int connectfd, struct sockaddr_in client);   main() {         int listenfd, connectfd; /* socket descriptors */         pid_t pid;         struct sockaddr_in server; /* server's address information */         struct sockaddr_in client; /* client's address information */         int sin_size;           /* Create TCP socket  */         if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {            /* handle exception */            perror("Creating socket failed.");            exit(1);            }           int opt = SO_REUSEADDR;         setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));           bzero(&server,sizeof(server));         server.sin_family=AF_INET;         server.sin_port=htons(PORT);         server.sin_addr.s_addr = htonl (INADDR_ANY);         if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {            /* handle exception */            perror("Bind error.");            exit(1);            }              if(listen(listenfd,BACKLOG) == -1){  /* calls listen() */            perror("listen() error\n");            exit(1);            }           sin_size=sizeof(struct sockaddr_in);           while(1)         {           /*accept connection.what causes the acceptance? */          if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {            perror("accept() error\n");            exit(1);            }         /*  Create child process to service client */         if ((pid=fork())>0) {            /* parent process */            close(connectfd);            continue;            }         else if (pid==0) {            /*child process*/            close(listenfd);            process_cli(connectfd, client);            exit(0);                }         else {            printf("fork error\n");            exit(0);            }         }         close(listenfd);   /* close listenfd */         }   void process_cli(int connectfd, struct sockaddr_in client) {         int num;         char recvbuf[MAXDATASIZE], sendbuf[MAXDATASIZE], cli_name[MAXDATASIZE];           printf("You got a connection from %s.  ",inet_ntoa(client.sin_addr) ); /* prints client's IP */         /* Get client's name from client */         num = recv(connectfd, cli_name, MAXDATASIZE,0);         if (num == 0) {            close(connectfd);            printf("Client disconnected.\n");            return;            }         cli_name[num - 1] = '\0';         printf("Client's name is %s.\n",cli_name);           while (num = recv(connectfd, recvbuf, MAXDATASIZE,0))         {                 int i = 0;                 recvbuf[num] = '\0';                 printf("Received client( %s ) message: %s",cli_name, recvbuf);                 for (i = 0; i < num - 1; i++) {                 sendbuf[i] = recvbuf[num - i -2];                 }                 sendbuf[num - 1] = '\0';                   send(connectfd,sendbuf,strlen(sendbuf),0); /* send to the client welcome message */         }         close(connectfd); /*  close connectfd */ }  
 
  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 // File: mult-thread-tcp-server.c
/* 多线程并发服务器。该程序实现多线程并发服务器 */   #include <stdio.h>          /* These are the usual header files */ //#include <strings.h>          /* for bzero() only <strings.h>  can not be compiled for memcpy in c++*/ #include <string.h>          /* for bzero() */ #include <unistd.h>         /* for close() */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <pthread.h> #include <stdlib.h>   /* for exit in c++(.C/.cc) ; no need for c ??*/   #define PORT 1234   /* Port that will be opened */ #define BACKLOG 5   /* Number of allowed connections */ #define MAXDATASIZE 1000    //void process_cli(int connectfd, sockaddr_in client); // c only supports struct sockaddr_in, but c++ support sockaddr_in void process_cli(int connectfd, struct sockaddr_in client); /* function to be executed by the new thread */ void* start_routine(void* arg); typedef struct  _ARG  {    int connfd;    struct sockaddr_in client;  }ARG; // it's better to use typedef struct main() {         int listenfd, connectfd; /* socket descriptors */         pthread_t  thread;         //struct ARG *arg;           // when no typedef,there should be struct for c code; no need for c++          ARG *arg;         struct sockaddr_in server; /* server's address information */         struct sockaddr_in client; /* client's address information */         int sin_size;           /* Create TCP socket */         if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {            /* handle exception */            perror("Creating socket failed.");            exit(1);         }           int opt = SO_REUSEADDR;         setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));           bzero(&server,sizeof(server));         server.sin_family=AF_INET;         server.sin_port=htons(PORT);         server.sin_addr.s_addr = htonl (INADDR_ANY);         if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {            /* handle exception */            perror("Bind error.");            exit(1);            }              if(listen(listenfd,BACKLOG) == -1){  /* calls listen() */            perror("listen() error\n");            exit(1);            }           sin_size=sizeof(struct sockaddr_in);         while(1)         {            /* Accept connection */           // if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {// no problem for c           if ((connectfd = accept(listenfd,(struct sockaddr *)&client,(socklen_t *)&sin_size))==-1) {               perror("accept() error\n");               exit(1);               }            /*  Create thread*/              arg = new  ARG;            arg->connfd = connectfd;            //memcpy((void *)&arg->client, &client, sizeof(client)); // both ok!            memcpy(&arg->client, &client, sizeof(client));              if (pthread_create(&thread, NULL, start_routine, (void*)arg)) {               /* handle exception */               perror("Pthread_create() error");               exit(1);               }         }         close(listenfd);   /* close listenfd */         }   void process_cli(int connectfd, sockaddr_in client) {         int num;         char recvbuf[MAXDATASIZE], sendbuf[MAXDATASIZE], cli_name[MAXDATASIZE];           printf("You got a connection from %s.  ",inet_ntoa(client.sin_addr) );         /* Get client's name from client */         num = recv(connectfd, cli_name, MAXDATASIZE,0);         if (num == 0) {            close(connectfd);            printf("Client disconnected.\n");            return;            }         cli_name[num - 1] = '\0';         printf("Client's name is %s.\n",cli_name);           while (num = recv(connectfd, recvbuf, MAXDATASIZE,0)) {            recvbuf[num] = '\0';            printf("Received client( %s ) message: %s",cli_name, recvbuf);            for (int i = 0; i < num - 1; i++) {               sendbuf[i] = recvbuf[num - i -2];               }            sendbuf[num - 1] = '\0';            send(connectfd,sendbuf,strlen(sendbuf),0);            }         close(connectfd); /*  close connectfd */ }   void* start_routine(void* arg) {         ARG *info;         info = (ARG *)arg;           /* handle client's requirement */         process_cli(info->connfd, info->client);           ////delete arg will cause warning!the type for deleting should be the same as new allocated         delete info;         pthread_exit(NULL); }     
 

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 // File:singlethread-mult-tcp-server.C
/*单线程并发服务器实例。该程序采用单线程并发服务器算法实现的。*/ #include <stdio.h>          /* These are the usual header files */ #include <string.h>          /* for bzero() */ #include <unistd.h>         /* for close() */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/time.h> #include <stdlib.h>   #define PORT 1234   /* Port that will be opened */ #define BACKLOG 5   /* Number of allowed connections simutaniously*/ #define MAXDATASIZE 1000 typedef struct _CLIENT{    int       fd;    char*  name;    struct sockaddr_in addr; /* client's address information */    char* data;                                        } CLIENT;  void process_cli(CLIENT *client, char* recvbuf, int len); void savedata(char* recvbuf, int len, char* data);   main() {         int    i, maxi, maxfd,sockfd;         int    nready;         ssize_t      n;         fd_set      rset, allset;         int listenfd, connectfd; /* socket descriptors */             struct sockaddr_in server; /* server's address information */         /* client's information */         CLIENT client[FD_SETSIZE];         char recvbuf[MAXDATASIZE];         int sin_size;           /* Create TCP socket  */         if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {            /* handle exception */            perror("Creating socket failed.");            exit(1);            }           int opt = SO_REUSEADDR;         setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));           bzero(&server,sizeof(server));         server.sin_family=AF_INET;         server.sin_port=htons(PORT);         server.sin_addr.s_addr = htonl (INADDR_ANY);         if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {            /* handle exception */            perror("Bind error.");            exit(1);            }              if(listen(listenfd,BACKLOG) == -1){  /* calls listen() */            perror("listen() error\n");            exit(1);            }           sin_size=sizeof(struct sockaddr_in);         /*initialize for select */         maxfd = listenfd;              maxi = -1;                        for (i = 0; i < FD_SETSIZE; i++) {            client[i].fd = -1;              }         FD_ZERO(&allset);         FD_SET(listenfd, &allset);           while(1)         {         struct sockaddr_in addr;         rset = allset;                     nready = select(maxfd+1, &rset, NULL, NULL, NULL);         printf("select saw rset actions and the readfset num is %d. \n",nready );           if (FD_ISSET(listenfd, &rset))         {      /* new client connection */                 /* Accept connection */                 printf("accept a connection.\n");                 if ((connectfd = accept(listenfd,(struct sockaddr *)&addr,(socklen_t *)&sin_size))==-1) {                 perror("accept() error\n");                 continue;                 }                   /* Put new fd to client */                 for (i = 0; i < FD_SETSIZE; i++)                 if (client[i].fd < 0) {                 client[i].fd = connectfd;    /* save descriptor */                 client[i].name = new char[MAXDATASIZE];                 client[i].addr = addr;                 client[i].data = new char[MAXDATASIZE];                 client[i].name[0] = '\0';                 client[i].data[0] = '\0';                 printf("You got a connection from %s.  ",inet_ntoa(client[i].addr.sin_addr) );                 break;                 }                   printf("add new connect fd.\n");                 if (i == FD_SETSIZE)          printf("too many clients\n");                 FD_SET(connectfd, &allset);   /* add new descriptor to set */                 if (connectfd > maxfd)  maxfd = connectfd;                    if (i > maxi)      maxi = i;                           if (--nready <= 0) continue;       /* no more readable descriptors */         }           for (i = 0; i <= maxi; i++)         {                      /* check all clients for data */                 if ( (sockfd = client[i].fd) < 0)   continue; /* no  more connected clients*/                                 if (FD_ISSET(sockfd, &rset)) {                 printf("recv occured for connect fd[%d].\n",i);                 if ( (n = recv(sockfd, recvbuf, MAXDATASIZE,0)) == 0) {                 /*connection closed by client */                 close(sockfd);                 printf("Client( %s ) closed connection. User's data: %s\n",client[i].name,client[i].data);                 FD_CLR(sockfd, &allset);                 client[i].fd = -1;                 delete client[i].name;                 delete client[i].data;                 } else                 process_cli(&client[i], recvbuf, n);                 if (--nready <= 0)     break;      /* no more readable descriptors */                 }         }         }         close(listenfd);   /* close listenfd */         }   void process_cli(CLIENT *client, char* recvbuf, int len) {         char sendbuf[MAXDATASIZE];           recvbuf[len-1] = '\0';         if (strlen(client->name) == 0) {            /* Got client's name from client */            memcpy(client->name,recvbuf, len);            printf("Client's name is %s.\n",client->name);            return;            }           /* save client's data */         printf("Received client( %s ) message: %s\n",client->name, recvbuf);         /* save user's data */         savedata(recvbuf,len, client->data);         /* reverse usr's data */         for (int i1 = 0; i1 < len - 1; i1++) {            sendbuf[i1] = recvbuf[len - i1 -2];         }         sendbuf[len - 1] = '\0';           send(client->fd,sendbuf,strlen(sendbuf),0); }   void savedata(char* recvbuf, int len, char* data) {         int start = strlen(data);         for (int i = 0; i < len; i++) {            data[start + i] = recvbuf[i];         }         }
 
  本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/sailor_8318/archive/2008/12/30/3658912.aspx
相关阅读 更多 +
排行榜 更多 +
盒子小镇2游戏手机版下载

盒子小镇2游戏手机版下载

冒险解谜 下载
世界盒子模组版下载最新版本

世界盒子模组版下载最新版本

模拟经营 下载
音乐搜索app最新版本下载

音乐搜索app最新版本下载

趣味娱乐 下载