常见web服务器模型集合
来源:互联网 发布:php get 加密 编辑:程序博客网 时间:2024/05/17 15:58
一)采用多进程模式的web服务器
//=============================================================// 文件名称:web.c// 功能描述:HTTP Server// 维护记录:2011-11-10 V1.0// 维护成员: tianmo//=============================================================#include <stdio.h>#include <stdlib.h>#include <string.h> // bzero#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h> // inet_ntop#include <pthread.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>//=============================================================// 语法格式: void main(void)// 实现功能: 主函数,建立一个HTTP Server// 入口参数: 无// 出口参数: 无//=============================================================int main(int argc, char *argv[]){ int sockfd; // 套接字 pid_t pid; //进程ID struct sockaddr_in servAddr; // 服务器地址结构体 struct sockaddr_in cliAddr; // 用于保存客户端地址 char cliIP[INET_ADDRSTRLEN]; // 用于保存客户端IP地址 unsigned short port = 80; // 监听端口 char head[]="HTTP/1.1 200 OK\r\n"\ "Content-Type: text/html\r\n"\ "\r\n"; char err[]="HTTP/1.1 404 Not Found\r\n"\ "Content-Type: text/html\r\n"\ "\r\n" \"<HTML><BODY>File not found</BODY></HTML>"; size_t cliAddrLen = sizeof(cliAddr); //计算客户端的地址大小 if(argc > 1) // 由参数接收端口 { port = atoi(argv[1]); } printf("TCP Server Started at port %d!\n", port); sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字 if(sockfd < 0) { perror("Invalid socket"); exit(1); } memset(&servAddr,0,sizeof(servAddr));// 初始化服务器地址 servAddr.sin_family = AF_INET; servAddr.sin_port = htons(port); servAddr.sin_addr.s_addr = htonl(INADDR_ANY); printf("Binding server to port %d\n", port); if(bind(sockfd, (struct sockaddr*)&servAddr, sizeof(struct sockaddr)) != 0) //bind绑定套接字 { close(sockfd); perror("binding err!"); exit(1); } if(listen(sockfd, 1) != 0)//listen监听套接字 { close(sockfd); perror("listen err!"); exit(1); } printf("waiting client ...\n"); while(1) { int connfd = accept(sockfd, (struct sockaddr*)&cliAddr, &cliAddrLen);//等待服务器访问 printf("the connfd = *%d*\n",connfd); inet_ntop(AF_INET, &cliAddr.sin_addr.s_addr, cliIP, INET_ADDRSTRLEN); printf("client ip = %s\n", cliIP); pid = fork(); //创建进程 if(pid == 0) { close(sockfd); //子进程中关闭主套接字 char recvbuf[1024]=""; // 接收缓冲区 char filename[100]; int openfd; char filebuf[1024]; read(connfd,recvbuf,1024);//从套接字中读取浏览器发送过来的数据. sscanf(recvbuf,"GET /%[^ ]",filename); //获取要浏览器请求的文件 printf("filename = *%s*\n",filename); openfd = open(filename,O_RDONLY); //打开浏览器请求的文件 if(openfd == -1) { printf("the file open error!\n"); write(connfd,err,strlen(err)); //文件打开失败发送错误提示 } else { printf("the file open successful!\n"); //注意这里是用strlen(head),而不是sizeof(),用sizeof将会导致图片打不开 send(connfd,head,strlen(head),0); //向浏览器发送请求OK的消息 int readflag = 0; //将打开的文件中的数据依次的发送给浏览器 while((readflag=read(openfd,filebuf,sizeof(filebuf))) > 0) { printf("readflag = *%d*\n",readflag); send(connfd,filebuf,readflag,0);//这里的发送数据大小为readflag,注意 } } close(connfd);//本次请求结束后关闭套接字 exit(0);//退出进程 } else { close(connfd);//主进程要关闭子进程中用到的套接字,不然再次有请求时,会导致网页始终打不开. } } close(sockfd); return 0;}
//http://wenku.baidu.com/view/ddc50e39580216fc700afd4d.html/*================================================================purpose:* Fork 模型TCP并发服务器demoNotes:* 采用TCP短连接,服务器将接收到从不同客户端传来的消息并打印到终端* 编译:gcc fork.c -0 forkAuthor:* tianmoDate:* 10th Feb 2012Updates:*================================================================*/#include <netinet/in.h> //for sockaddr_in#include <sys/types.h> //for socket#include <stdio.h> //for printf#include <stdlib.h> //for exit#include <string.h> //for bzero#include <unistd.h> // for fork#include <sys/signal.h> // for signal#include <sys/wait.h> // for wait#define HELLO_WORLD_SERVER_PORT 8888#define LENGTH_OF_LISTEN_QUEUE 20#define BUFFER_SIZE 1024void reaper(int sig){int status;//调用wait3读取子进程的返回值,使zombie状态的子进程彻底释放while(wait3(&status,WNOHANG,(struct rusage *)0) >= 0);}int main(){//设置一个socket地址结构server_addr,代表服务器internet地址,端口struct sockaddr_in server_addr;bzero(&server_addr,sizeof(server_addr));//把一段内存中区的全部内容设置为0server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = htons(INADDR_ANY);server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);//创建用于internet的流协议(TCP)socket,用server_socket代表服务器socketint server_socket = socket(AF_INET,SOCK_STREAM,0);if(server_socket < 0){printf(Create Socket Failed.");exit(1);}//把socket和socket地址结构联系起来if(bind(server_socket,(struct sockaddr *)&server_addr,sizeof(server_addr))){printf("Server Bind Port : %d\n",HELLO_WORLD_SERVER_PORT);exit(1);}//server_socket用于监听if(listen(server_socket,LENGTH_OF_LISTEN_QUEUE)){printf("Server Listen Failed!");exit(1);}//通知操作系统,当收到子进程的退出信号(SIGCHLD),执行reaper函数,释放zombie状态的进程(void)signal(SIGCHLD,reaper);while(1)//服务器端需要一直运行{//定义客户端的socket地址结构client_addrstruct sockaddr_in client_addr;socklen_t length = sizeof(client_addr);int new_server_socket;//接受一个到server_socket代表的socket的一个连接//如果没有连接请求,就等待到有连接请求--这是accept函数的特性//accept函数返回一个新的socket,这个socket(new_server_socket)用于同连接到的客户通信//new_server_socket代表了服务器和客户端之间的一个通道//accept函数把连接到的客户端信息填写到客户端的socket地址结构client_addr中new_server_socket = accept(server_socket,(struct sockaddr *)&client_addr,&length);if(new_server_socket < 0){printf("Server Accept Failed!\n");break;}int child_process_pid = fork();//fork()后,子进程是主进程的拷贝//在主进程和子进程中的区别是fork()的返回值不同 if(0 == child_process_pid)//如果当前进程是子进程,就执行与客户端的交互{close(server_socket);//子进程中不需要被复制过来的server_socketchar buffer[BUFFER_SIZE];bzero(buffer,BUFFER_SIZE * sizeof(char));strcpy(buffer,"Hello world!从服务器来!");strcat(buffer,"\n");//C语言字符串连接//发送buffer中的字符串倒new_server_socket,实际是给客户端send(new_server_socket,buff,BUFFER_SIZE,0);bzero(buffer,BUFFER_SIZE);//接收客户端发送过来的信息到buffer中length = recv(new_server_socket,buffer,BUFFER_SIZE,0);if(length < 0){printf("Server Receive Data Failed!\n");exit(1);}printf("\n%s",buffer);//关闭与客户端的连接close(new_server_socket);//TCP短连接exit(0);}else if(child_process_pid > 0)//如果当前进程是主进程close(new_server_socket);//主进程中不需要用于同客户端交互的new_server_socket}//关闭监听用的socketclose(server_socket);return 0;}二)文件传输服务器和客户端程序
//////////////////////////////////////////////////////////////////////////////////////// file_server.c 文件传输顺序服务器示例////////////////////////////////////////////////////////////////////////////////////////本文件是服务器的代码#include <netinet/in.h> // for sockaddr_in#include <sys/types.h> // for socket#include <sys/socket.h> // for socket#include <stdio.h> // for printf#include <stdlib.h> // for exit#include <string.h> // for bzero/*#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>*/#define HELLO_WORLD_SERVER_PORT 6666 #define LENGTH_OF_LISTEN_QUEUE 20#define BUFFER_SIZE 1024#define FILE_NAME_MAX_SIZE 512int main(int argc, char **argv){ //设置一个socket地址结构server_addr,代表服务器internet地址, 端口 struct sockaddr_in server_addr; bzero(&server_addr,sizeof(server_addr)); //把一段内存区的内容全部设置为0 server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htons(INADDR_ANY); server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT); //创建用于internet的流协议(TCP)socket,用server_socket代表服务器socket int server_socket = socket(PF_INET,SOCK_STREAM,0); if( server_socket < 0) { printf("Create Socket Failed!"); exit(1); } //把socket和socket地址结构联系起来 if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr))) { printf("Server Bind Port : %d Failed!", HELLO_WORLD_SERVER_PORT); exit(1); } //server_socket用于监听 if ( listen(server_socket, LENGTH_OF_LISTEN_QUEUE) ) { printf("Server Listen Failed!"); exit(1); } while (1) //服务器端要一直运行 { //定义客户端的socket地址结构client_addr struct sockaddr_in client_addr; socklen_t length = sizeof(client_addr); //接受一个到server_socket代表的socket的一个连接 //如果没有连接请求,就等待到有连接请求--这是accept函数的特性 //accept函数返回一个新的socket,这个socket(new_server_socket)用于同连接到的客户的通信 //new_server_socket代表了服务器和客户端之间的一个通信通道 //accept函数把连接到的客户端信息填写到客户端的socket地址结构client_addr中 int new_server_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length); if ( new_server_socket < 0) { printf("Server Accept Failed!\n"); break; } char buffer[BUFFER_SIZE]; bzero(buffer, BUFFER_SIZE); length = recv(new_server_socket,buffer,BUFFER_SIZE,0); if (length < 0) { printf("Server Recieve Data Failed!\n"); break; } char file_name[FILE_NAME_MAX_SIZE+1]; bzero(file_name, FILE_NAME_MAX_SIZE+1); strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buffer));// int fp = open(file_name, O_RDONLY);// if( fp < 0 ) FILE * fp = fopen(file_name,"r"); if(NULL == fp ) { printf("File:\t%s Not Found\n", file_name); } else { bzero(buffer, BUFFER_SIZE); int file_block_length = 0;// while( (file_block_length = read(fp,buffer,BUFFER_SIZE))>0) while( (file_block_length = fread(buffer,sizeof(char),BUFFER_SIZE,fp))>0) { printf("file_block_length = %d\n",file_block_length); //发送buffer中的字符串到new_server_socket,实际是给客户端 if(send(new_server_socket,buffer,file_block_length,0)<0) { printf("Send File:\t%s Failed\n", file_name); break; } bzero(buffer, BUFFER_SIZE); }// close(fp); fclose(fp); printf("File:\t%s Transfer Finished\n",file_name); } //关闭与客户端的连接 close(new_server_socket); } //关闭监听用的socket close(server_socket); return 0;}
//////////////////////////////////////////////////////////////////////////////////////// file_client.c 文件传输客户端程序示例////////////////////////////////////////////////////////////////////////////////////////本文件是客户机的代码#include <netinet/in.h> // for sockaddr_in#include <sys/types.h> // for socket#include <sys/socket.h> // for socket#include <stdio.h> // for printf#include <stdlib.h> // for exit#include <string.h> // for bzero/*#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>*/#define HELLO_WORLD_SERVER_PORT 6666 #define BUFFER_SIZE 1024#define FILE_NAME_MAX_SIZE 512int main(int argc, char **argv){ if (argc != 2) { printf("Usage: ./%s ServerIPAddress\n",argv[0]); exit(1); } //设置一个socket地址结构client_addr,代表客户机internet地址, 端口 struct sockaddr_in client_addr; bzero(&client_addr,sizeof(client_addr)); //把一段内存区的内容全部设置为0 client_addr.sin_family = AF_INET; //internet协议族 client_addr.sin_addr.s_addr = htons(INADDR_ANY);//INADDR_ANY表示自动获取本机地址 client_addr.sin_port = htons(0); //0表示让系统自动分配一个空闲端口 //创建用于internet的流协议(TCP)socket,用client_socket代表客户机socket int client_socket = socket(AF_INET,SOCK_STREAM,0); if( client_socket < 0) { printf("Create Socket Failed!\n"); exit(1); } //把客户机的socket和客户机的socket地址结构联系起来 if( bind(client_socket,(struct sockaddr*)&client_addr,sizeof(client_addr))) { printf("Client Bind Port Failed!\n"); exit(1); } //设置一个socket地址结构server_addr,代表服务器的internet地址, 端口 struct sockaddr_in server_addr; bzero(&server_addr,sizeof(server_addr)); server_addr.sin_family = AF_INET; if(inet_aton(argv[1],&server_addr.sin_addr) == 0) //服务器的IP地址来自程序的参数 { printf("Server IP Address Error!\n"); exit(1); } server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT); socklen_t server_addr_length = sizeof(server_addr); //向服务器发起连接,连接成功后client_socket代表了客户机和服务器的一个socket连接 if(connect(client_socket,(struct sockaddr*)&server_addr, server_addr_length) < 0) { printf("Can Not Connect To %s!\n",argv[1]); exit(1); } char file_name[FILE_NAME_MAX_SIZE+1]; bzero(file_name, FILE_NAME_MAX_SIZE+1); printf("Please Input File Name On Server:\t"); scanf("%s", file_name); char buffer[BUFFER_SIZE]; bzero(buffer,BUFFER_SIZE); strncpy(buffer, file_name, strlen(file_name)>BUFFER_SIZE?BUFFER_SIZE:strlen(file_name)); //向服务器发送buffer中的数据 send(client_socket,buffer,BUFFER_SIZE,0);// int fp = open(file_name, O_WRONLY|O_CREAT);// if( fp < 0 ) FILE * fp = fopen(file_name,"w"); if(NULL == fp ) { printf("File:\t%s Can Not Open To Write\n", file_name); exit(1); } //从服务器接收数据到buffer中 bzero(buffer,BUFFER_SIZE); int length = 0; while( length = recv(client_socket,buffer,BUFFER_SIZE,0)) { if(length < 0) { printf("Recieve Data From Server %s Failed!\n", argv[1]); break; }// int write_length = write(fp, buffer,length); int write_length = fwrite(buffer,sizeof(char),length,fp); if (write_length<length) { printf("File:\t%s Write Failed\n", file_name); break; } bzero(buffer,BUFFER_SIZE); } printf("Recieve File:\t %s From Server[%s] Finished\n",file_name, argv[1]); fclose(fp); //关闭socket close(client_socket); return 0;}使用方法:
服务器端程序的编译:gcc -o file_server file_server.c
客户端程序的编译:gcc -o file_client file_client.c
服务器程序和客户端程应当分别运行在2台计算机上.
服务器端程序的运行,在一个计算机的终端执行:./file_server
客户端程序的运行,在另一个计算机的终端中执行:./file_client
运行服务器程序的计算机的IP地址,根据提示输入要传输的服务器上的文件,该文件在服务器的运行目录上,在实际编程和测试中,可以用2个终端代替2个计算机,这样就可以在一台计算机上测试网络程序。
服务器端程序的运行,在一个终端执行:./file_server,客户端程序的运行;在另一个终端中执行:./file_client 127.0.0.1
说明: 任何计算机都可以通过127.0.0.1访问自己. 也可以用计算机的实际IP地址代替127.0.0.1
- 常见web服务器模型集合
- 常见嵌入式WEB服务器
- 常见嵌入式WEB服务器
- 常见嵌入式WEB服务器
- 常见web服务器
- WEB服务器常见漏洞
- 常见嵌入式WEB服务器
- 常见web服务器一览
- 常见web服务器错误
- Web服务器常见安全漏洞
- 常见Web服务器简介
- 常见嵌入式WEB服务器
- 常见的web服务器
- 常见web服务器简介
- web服务器变量集合
- WEB服务器的常见漏洞
- 常见的Java WEB服务器
- 常见的Java WEB服务器
- 丢掉笨重SQL Server Management,直接用eclipse管理数据库
- 嵌入式Web服务器BOA和CGI编程开发
- Java生成验证码图片
- Excel 中添加日期控件
- POJ 1287 Networking(prime算法)
- 常见web服务器模型集合
- 查询、删除、添加、修改SQL语句
- Effective C++读书笔记之七
- 二维数组做得五子棋(基于控制台)
- 如何解决ORA-00054资源正忙,要求指定NOWAIT?
- mysql 列转行
- 中秋生活
- 由米聊、微信谈熟人社区OR生人社区构建社交网络的优势和劣势
- recyclebin回收站功能