Linux多进程并发的服务器,其原理是:
1、Linux下fork创建新进程,子进程会复制父进程资源,即子进程会复制父进程中文件、文件系统、虚拟内存等结构。
2、close()函数关闭描述符,只是将访问计数值减1,当描述符的计数值为0时,描述符才会真正关闭。
所以Linux多进程并发服务器的工作流程是这样的:
父进程负责接收处理客户请求,其后调用fork建立子进程,此时监听与已连接描述符相关连的文件表象的访问计数值均加1,子进程调用close函数关闭监听描述符,其后处理用户请求。父进程继续等待接收处理客户请求。
示例程序建立一个多进程并发服务器程序和一个客户端程序,服务器程序将客户端发过来的字符串中的小写字母全部转化为大学字母后发回客户端。
服务器程序代码:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #define MAXDATASIZE 1024
- #define PORT 1111
- #define BACKLOG 5
- void process(int connectfd){
- char buf[MAXDATASIZE];
- int num=0;
- while(0<(num=read(connectfd,buf,sizeof(buf)))){
- buf[num]='\0';
- if(0==strcmp(buf,"bye"))
- break;
- int i=0;
- puts(buf);
- while(buf[i]){
- if(buf[i]>='a'&&buf[i]<='z')
- buf[i]=buf[i]-'a'+'A';
- i++;
- }
- write(connectfd,buf,strlen(buf));
- }
- close(connectfd);
- }
- int main(){
- int listenfd,connectfd;
- struct sockaddr_in server;
- struct sockaddr_in client;
- int len;
- pid_t pid;
- if(-1==(listenfd=socket(AF_INET,SOCK_STREAM,0))){
- perror("create socket error");
- 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(-1==bind(listenfd,(struct sockaddr *)&server,sizeof(struct sockaddr ))){
- perror("bind error\n");
- exit(1);
- }
- if(-1==listen(listenfd,BACKLOG)){
- perror("listen error\n");
- exit(1);
- }
- len=sizeof(client);
- while(1){
- if(-1==(connectfd=accept(listenfd,(struct sockaddr *)&client,&len))){
- perror("connect error\n");
- exit(1);
- }
- if((pid=fork())<0){
- perror("fork error\n");
- exit(1);
- }
- else if(0==pid){
- close(listenfd);
- printf("Got a connection from %s. \n",inet_ntoa(client.sin_addr));
- process(connectfd);
- exit(0);
- }
- }
- close(listenfd);
- return 0;
- }
客户端代码:
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #define PORT 1111
- #define MAXDATASIZE 1024
- int main(int argc,char **argv){
- int sockfd;
- char buf[MAXDATASIZE];
- struct hostent *he;
- struct sockaddr_in server;
- if(2>argc){
- fprintf(stderr,"Usage: %s \n",argv[0]);
- exit(1);
- }
- if(NULL==(he=gethostbyname(argv[1]))){
- perror("gethostbyname error\n");
- exit(1);
- }
- if(-1==(sockfd=socket(AF_INET,SOCK_STREAM,0))){
- perror("socket error\n");
- exit(1);
- }
- bzero(&server,sizeof(server));
- server.sin_family=AF_INET;
- server.sin_port=htons(PORT);
- server.sin_addr = *((struct in_addr*)he->h_addr);
- if(-1==connect(sockfd,(struct sockaddr*)&server,sizeof(struct sockaddr))){
- perror("connect error\n");
- exit(1);
- }
- while(1){
- gets(buf);
- write(sockfd,buf,strlen(buf));
- printf("send %s to server\n",buf);
- int num=read(sockfd,buf,sizeof(buf));
- buf[num]='\0';
- puts(buf);
- }
- close(sockfd);
- return 0;
- }
demo.zip
阅读(5932) | 评论(0) | 转发(2) |