天天看点

1高并发服务器:多进程服务器



1多进程并发服务器

使用多进程并发服务器时要考虑以下几点:

a.父最大文件描述个数(父进程中需要close关闭accept返回的新文件描述符)

b.系统内创建进程个数(和内存大小相关)

c.进程创建过多是否降低整体服务性能(进程调度)

2.案例说明

server.c,代码如下:

#include <stdio.h>

#include <string.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <signal.h>

#include <sys/wait.h>

#include <sys/types.h>

#include <ctype.h>

#include <unistd.h>

#include "wrap.h"

#define maxline 80

#define serv_port 8000

void do_sigchild(int num) {

waitpid(0,null,wnohang);

}

int main(void) {

struct sockaddr_in servaddr,cliaddr;

socklen_t cliaddr_len;

int listenfd,connfd;

char buf[maxline];

//inet_addrstrlen是ip地址的最大长度,是系统定义的一个宏

char str[inet_addrstrlen];

int i,n;

pid_t pid;

struct sigaction newact;

newact.sa_handler = do_sigchild;

sigemptyset(&newact.sa_mask);

newact.sa_flags = 0;

//发信号

sigaction(sigchld,&newact,null);

//1.这里建立一个tcp的连接,因为是sock_stream的,表示的是tcp的

listenfd = socket(af_inet,sock_stream,0);

//将seraddr内容清零

bzero(&servaddr,sizeof(servaddr));

servaddr.sin_family = af_inet;

servaddr.sin_addr.s_addr = htonl(inaddr_any);

servaddr.sin_port = htons(serv_port);

//2.绑定ip地址和端口号

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

//监听,最多的可以是20个

listen(listenfd,20);

printf("accepting connections...\n");

while(1) {

cliaddr_len = sizeof(cliaddr_len);

//connfd:这里才是后续进程需要用的文件描述符

//listenfd:已经不用里,可以被销毁,这个程序是在子进程里面销毁

connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&cliaddr_len);

pid = fork();

if(pid ==0) {

if(pid == 0) {

close(listenfd);

n = read(connfd,buf,maxline);

if(n == 0) {

      printf("the other side has been closed.\n");

break;

printf("received from %s at port %d\n",

inet_ntop(af_inet,&cliaddr.sin_addr.s_addr,str,sizeof(str)),

                 ntohs(cliaddr.sin_port));

for(i = 0; i< n; i++) {

buf[i] = toupper(buf[i]);

write(connfd,buf,n);

close(connfd);

return 0;

} else if(pid > 0) {

} else {

perr_exit("fork");

client.c

int main(int argc,char *argv[]) {

struct sockaddr_in servaddr;

int sockfd,n;

sockfd = socket(af_inet,sock_stream,0);

inet_pton(af_inet,"127.0.0.1",&servaddr.sin_addr.s_addr);

connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

while(fgets(buf,maxline,stdin) != null) {

write(sockfd,buf,strlen(buf));

n = read(sockfd,buf,maxline);

printf("the other side has ben closed.\n");

write(stdout_fileno,buf,n);

close(sockfd);

wrap.h

#ifndef __wrap_h_

#define __wrap_h_

void perr_exit(const char *s);

int accept(int fd, struct sockaddr *sa, socklen_t *salenptr);

void bind(int fd, const struct sockaddr *sa, socklen_t salen);

void connect(int fd, const struct sockaddr *sa, socklen_t salen);

void listen(int fd, int backlog);

int socket(int family, int type, int protocol);

ssize_t read(int fd, void *ptr, size_t nbytes);

ssize_t write(int fd, const void *ptr, size_t nbytes);

void close(int fd);

ssize_t readn(int fd, void *vptr, size_t n);

ssize_t writen(int fd, const void *vptr, size_t n);

static ssize_t my_read(int fd, char *ptr);

ssize_t readline(int fd, void *vptr, size_t maxlen);

#endif

wrap.c

#include <stdlib.h>

#include <errno.h>

#include <sys/socket.h>

void perr_exit(const char *s)

{

perror(s);

exit(1);

int accept(int fd, struct sockaddr *sa, socklen_t *salenptr)

int n;

again:

if ( (n = accept(fd, sa, salenptr)) < 0) {

if ((errno == econnaborted) || (errno == eintr))

goto again;

else

perr_exit("accept error");

return n;

void bind(int fd, const struct sockaddr *sa, socklen_t salen)

if (bind(fd, sa, salen) < 0)

perr_exit("bind error");

void connect(int fd, const struct sockaddr *sa, socklen_t salen)

if (connect(fd, sa, salen) < 0)

perr_exit("connect error");

void listen(int fd, int backlog)

if (listen(fd, backlog) < 0)

perr_exit("listen error");

int socket(int family, int type, int protocol)

if ( (n = socket(family, type, protocol)) < 0)

perr_exit("socket error");

ssize_t read(int fd, void *ptr, size_t nbytes)

ssize_t n;

if ( (n = read(fd, ptr, nbytes)) == -1) {

if (errno == eintr)

return -1;

ssize_t write(int fd, const void *ptr, size_t nbytes)

if ( (n = write(fd, ptr, nbytes)) == -1) {

void close(int fd)

if (close(fd) == -1)

perr_exit("close error");

ssize_t readn(int fd, void *vptr, size_t n)

size_t  nleft;

ssize_t nread;

char   *ptr;

ptr = vptr;

nleft = n;

while (nleft > 0) {

if ( (nread = read(fd, ptr, nleft)) < 0) {

                            nread = 0;

} else if (nread == 0)

nleft -= nread;

ptr += nread;

return n - nleft;

ssize_t writen(int fd, const void *vptr, size_t n)

size_t nleft;

ssize_t nwritten;

const char *ptr;

if ( (nwritten = write(fd, ptr, nleft)) <= 0) {

if (nwritten < 0 && errno == eintr)

nwritten = 0;

nleft -= nwritten;

ptr += nwritten;

static ssize_t my_read(int fd, char *ptr)

static int read_cnt;

static char *read_ptr;

static char read_buf[100];

if (read_cnt <= 0) {

if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {

} else if (read_cnt == 0)

read_ptr = read_buf;

read_cnt--;

*ptr = *read_ptr++;

return 1;

ssize_t readline(int fd, void *vptr, size_t maxlen)

ssize_t n, rc;

char    c, *ptr;

for (n = 1; n < maxlen; n++) {

if ( (rc = my_read(fd, &c)) == 1) {

*ptr++ = c;

if (c  == '\n')

} else if (rc == 0) {

*ptr = 0;

return n - 1;

*ptr  = 0;

运行结果(编译server):

1高并发服务器:多进程服务器

运行client端

1高并发服务器:多进程服务器

继续阅读