Unix网络编程服务器设计方式之二

为每个客户端创建一个线程

此方式首先服务器端建立一个监听,并阻塞至accetp处,当一个客户端进行连接时,accept函数并激活并返回,此时用fork函数创建一个子进程,由子进程执行客户请求处理程序,而父进程继续监听,等待其他的客户端。此方式会创建很多的进程,进程个数受具体的操作系统的限制。这种并发服务器的缺点在于创建一个子进程花费的CPU时间较多,如现在的WEB服务一天需要处理百万计的连接,为每个连接创建一个子进程就会浪费很多的CPU时间,此可以通过预先创建进程的方法来解决,此将作为单独的一个模块说明。

 

例子:回射服务器,接受客户端的请求,并读取客户的数据并原样返回,此程序在CentOS 5.0中测试通过。

服务器程序:

#include <stdio.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/time.h>

#include <sys/select.h>

#include <strings.h>

#include <errno.h>

#include <stdlib.h>

 

#define SERV_PORT 2003

#define MAXLINE 1024

#define LISTENQ 4

 

/* 根据端口号建立连接 */

int makeListenByPort(short port)

{

   int listenfd;

   struct sockaddr_in servaddr;

 

   listenfd = socket(AF_INET, SOCK_STREAM, 0);

 

   bzero(&servaddr, sizeof(servaddr));

   servaddr.sin_family = AF_INET;

   servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

   servaddr.sin_port = htons(port);

 

   bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

 

   listen(listenfd, LISTENQ);

 

   return listenfd;

}

 

/* 客户请求处理函数 */

void requestProductFunc(int connfd)

{

  char buf[MAXLINE];

  int n;

 

  for(;;) {

      if((n = read(connfd, buf, MAXLINE)) == 0) {

          close(connfd);

         printf("client is quit\n");

      }else{

          write(connfd, buf, n);

      }

   }

}

 

int main(int argc, char **argv)

{

   int listenfd, connfd, maxfd, sockfd;

   char buf[MAXLINE];

   struct sockaddr_in cliaddr;

   int i;

   int clilen, adrlen;

   pid_t child;

 

   listenfd = makeListenByPort(SERV_PORT);

   adrlen = sizeof(struct sockaddr);

 

   for(;;) {

       clilen = adrlen;

       if((connfd = accept(listenfd, (struct sockaddr *)&cliaddr,&clilen)) < 0){

           /* 如果是被中信号中断则继续*/

           if(errno == EINTR)

                continue;

           else{

                printf("accepterror!");

                exit(0);

           }

       }

 

       /* 创建一个线程并调用客户请求处理函数 */

       if((child = fork()) == 0) {

           close(listenfd);

           requestProductFunc(connfd);

           exit(0);

       }

  

      /* 父进程关闭连接,并继续监听 */

       close(connfd);

   }

}

 

客户端程序:

#include <stdio.h>

#include <stdlib.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <strings.h>

#include <string.h>

 

#define MAXLINE 1024

#define SERV_PORT 2003

 

void cli_str(FILE *fp, int sockfd)

{

   char sendline[MAXLINE];

   char recvline[MAXLINE];

 

   memset(recvline, 0x00, sizeof(recvline));

   memset(sendline, 0x00, sizeof(sendline));

   printf("cli#");

   while((fgets(sendline, MAXLINE, fp)) != NULL) {

       write(sockfd, sendline, strlen(sendline));

       if(read(sockfd, recvline, MAXLINE) == 0) {

           printf("str_cli:server terminated prematurely\n");

           exit(0);

       }

       fputs(recvline, stdout);

       fflush(stdout);

       memset(recvline, 0x00, sizeof(recvline));

       printf("cli#");

    }

}

 

int main(int argc, char **argv)

{

   int sockfd;

   struct sockaddr_in servaddr;

 

   if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

       printf("socket error\n");

       exit(0);

    }

 

   bzero(&servaddr, sizeof(servaddr));

   servaddr.sin_family = AF_INET;

   inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

   servaddr.sin_port = htons(SERV_PORT);

   if((connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)))== -1) {

       printf("connect error\n");

       exit(0);

    }

 

   cli_str(stdin, sockfd);

   exit(0);

}

 

阅读更多
个人分类: UNIX编程
上一篇Unix网络编程服务器设计方式之一
下一篇Unix网络编程服务器设计方式之三
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭