搭建简单的http服务器
来源:互联网 发布:淘宝借呗 编辑:程序博客网 时间:2024/06/06 06:35
开发语言C++,平台为Linux。
主要流程为:服务器获得请求–>响应并处理请求–>返回结果。
这里着重讲怎么处理请求。
主程序在获得一个请求后会开辟一个线程来处理请求
流程图如下。
hand_cgi函数流程图
cgi程序流程图。
代码:
#include"http.h"int ret = 0;void printf_log(string s){ //cout << s << endl;}int init_fd(int socketi, char* str){ sockaddr_in addr; bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(inet_addr(str)); addr.sin_port = htons(PORT); int err = bind(socketi, (struct sockaddr*)&addr, sizeof(addr)); if (err < 0){ printf_log("bind error"); ret = -1; } int on = 0; setsockopt( socketi, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ); err = listen(socketi, 5); if (err < 0){ printf_log("listen error"); ret = -1; } return socketi;}static int get_line(int fd, char *buf){ char ch = 0; char next = 0; int i = 0; int err = 0; while (ch != '\n'){ int size = read(fd, &ch, 1); if (size <= 0){ ch = '\n'; } if (ch != '\n' && ch != '\r'){ buf[i++] = ch; } else{ if (ch == '\r'){ err = recv(fd, &next, 1, MSG_PEEK); if (err < 0){ printf_log("recv error"); return -1; } if (next == '\n'){ err = read(fd, &ch, 1); if (err < 0){ printf_log("recv error"); return -1; } }//if ch = '\n'; } }//else }//whilebuf[i] = 0; return 1;}static void clean_header(int fd){ char ch[100] = {0}; get_line(fd, ch); while (strlen(ch) != 0){ get_line(fd, ch); }}static int hand_cgi(int fd, char* path, char * argument){ char line[SIZE/2] = {0}; char length[10] = {0}; int i_length = 0; char method[10] = {0}; if (strlen(argument) == 0){ sprintf(method, "METHOD=POST"); while (get_line(fd, line) > 0){ if (strncmp(line, "Content-Length", 16) == 0){ i_length = atoi(line + 16); break; } }//while clean_header(fd); sprintf(length, "Content-Length=%d", i_length); putenv(length); }//if else{ sprintf(method, "METHOD=GET"); char str[100] = {0}; sprintf(str, "QESTRING=%s", argument); if (putenv(str) < 0){ printf_log("she zhi huai jing cuo wu"); ret = -1; } clean_header(fd); }//else putenv(method); //reponse char request[] = "HTTP/1.0 200 OK\r\n"; write(fd, request, strlen(request)); int _std[2] = {0}; int _std2[2] = {0}; if (pipe(_std) < 0){ printf_log("pipe error"); ret = -1; } if (pipe(_std2) < 0){ printf_log("pipe2 error"); ret = -1; } pid_t pid = fork(); if (pid < 0){ printf_log("fork error"); ret = -1; return 0; } if (pid == 0){ close(_std[0]); close(_std2[1]); dup2(_std[1], 1); dup2(_std2[0], 0); execl(path,path, NULL); cout << "error" << endl; } else{ close(_std[1]); close(_std2[0]); int ch = 0; char string[SIZE/2] = {0}; for (int i = 0; i < i_length; i++){ read(fd, &ch, 1); string[i] = ch; } char buf[SIZE/2] = {0}; write(_std2[1], string, strlen(string)); read(_std[2], buf, SIZE/2); //返回输出 write(fd, buf, strlen(buf)); } close(_std[0]); close(_std2[1]); }}static void get(int fd){ char buf[2*SIZE]; char ch; int i = 0; while (read(fd, &ch, 1) > 0){ buf[i++] = ch; } // printf("%s\n", buf);}void *handler_in(void *arg){ pthread_detach(pthread_self()); char method[SIZE/2] = {0}; char buf[SIZE] = {0}; char line[SIZE/2] = {0}; char url[SIZE/2] = {0}; char goal[SIZE/2] = {0}; char argument[SIZE] = {0}; int err = 0; int cgi = 0; int i = 0; char request[] = "HTTP/1.1 200 OK\r\n"; //cout << 123 << endl; err = get_line((int)arg, line); if (err < 0){ ret = 1; goto end; } for (i = 0; line[i] != ' '; i++){ method[i] = line[i]; } i++; for (int j = 0; line[i] != ' '&&line[i] != '?'; i++){ url[j++] = line[i]; } //printf("%s\n" ,method); if (line[i] == '?'){ i++; for (int j = 0; line[i] != ' '&&line[i] != '?'; i++){ argument[j++] = line[i]; } } if (strcasecmp(method, "POSE") != 0 && strcasecmp(method, "GET") != 0){ printf_log("method"); ret = 2; goto end; } if (strcasecmp(method, "POSE") == 0) cgi = 1; if (strcasecmp(method, "GET") == 0 && argument[0] != 0) cgi = 1; if (strlen(url) == 1 && strcasecmp(url , "/") == 0) sprintf(goal, "wwwroot/root.html"); else sprintf(goal, "wwwroot%s", url); //判断文件 struct stat file; err = stat(goal, &file); if (err < 0){ ret = 3; printf_log("file not found"); goto end; } if (file.st_mode & S_IFDIR){ // } if (file.st_mode & S_IXUSR || file.st_mode & S_IXGRP || file.st_mode & S_IXOTH){ if (0 == cgi){ ret = 4; printf_log("文件类型与cgi不匹配"); goto end; } } if (1 == cgi){ err = hand_cgi((int)arg, goal, argument); }//cgi if else{ clean_header((int)arg); write((int)arg, request, strlen(request)); write((int)arg, "\r\n", 2); int fd = open(goal, O_RDONLY); err = sendfile((int)arg, fd, 0, file.st_size); if (err < 0){ ret = 5; printf_log("sendfile error"); printf("%d, %s\n", errno, strerror(errno)); } }//cgi elseend: close((int)arg);}
cgi程序示例(2数相加):
#include <iostream>#include <stdlib.h>#include <string.h>#include <stdio.h>#define SIZE 1024using namespace std;int hand(char *q){ char *num = NULL; char *num_2 = NULL; int num1 = 0; int num2 = 0; while (*q != '=') q++; q++; num = q; while (*q != '&') q++; *q = 0; num1 = atoi(num); while (*q != '=') q++; q++; num_2 = q; num2 = atoi(num_2); printf("<html>\n"); printf("<head><h2>%d + %d = %d</h2></head>\r\n", num1, num2, num1+num2); printf("</html>\n");}int main(){ printf("Content-Type:text/html;charset=ISO-8859-1\n\n"); char *p = NULL; int i_length = 0; char query_string[SIZE/2] = {0}; char *length = NULL; p = getenv("METHOD"); if (strcmp(p, "GET") == 0){ char *s = getenv("QESTRING"); memcpy(query_string, s, strlen(s)); }//if else{ length = getenv("Content-Length"); i_length = atoi(length); char ch = 0; for (int i = 0; i < i_length; i++){ ch = getc(0); query_string[i] = ch; } } hand(query_string); printf("\n"); return 0;}
运行:
发送请求
返回结果:
此外,我们可再写一个可以连接mysql数据库的cgi程序,这样我们就可以远程管理数据库了。
cgi程序:
#include<iostream>#include<cstdio>#include<cstdlib>#include<mysql.h>#include<cstring>using namespace std;const int SIZE = 100;//把值赋给相应的参数void static handing(char* &str, char* &query){ while (*query != '=') query++; str = ++query; while (*query != '&'&& *query != 0) query++; *query = 0; query++;}//取值static void hand_query(int &mod, char* &name, int &age, char *&where, char *query){ char *str = NULL; handing(str, query); mod = atoi(str); handing(where, query); handing(name, query); if (3 == mod) return; handing(str, query); age = atoi(str);}void find(MYSQL *conn, char *name, char *where){ MYSQL_RES *result; MYSQL_ROW row; char buf[100] = {0}; sprintf(buf, "SELECT * FROM %s", where); mysql_query(conn, buf); result = mysql_store_result(conn); if (NULL == result) cout << "NULL" << endl; int num_fields = mysql_num_fields(result); while ((row = mysql_fetch_row(result))){ if (strcmp(row[0], name) == 0) for (int i = 0; i < num_fields; i++){ printf("%s ", row[i] ? row[i] : "NULL"); } } mysql_free_result(result);}int hand(char *query){ int mod = 0; char *name = NULL; char buf[100] ={0}; int age = 0; char *where = NULL; hand_query(mod, name, age, where, query); MYSQL *conn = new MYSQL; conn = mysql_init(NULL); if (conn == NULL){ printf("ERROR %u: %s\n", mysql_errno(conn), mysql_error(conn)); exit(1); } if (mysql_real_connect(conn, "localhost", "root", NULL, "tq", 0, NULL, 0)==NULL){ printf("ERROR %u:%s\n", mysql_errno(conn), mysql_error(conn)); exit(1); } //这里只列举最简单的find操作 switch(mod){ case 1:creat(conn, name, age, where); break; case 2:insert(conn, name, age,where); break; case 3:find(conn, name,where); break; case 4:modifier(conn, name, age, where); break; case 5:my_delete(conn, name, where); default: break; } mysql_close(conn);}int main(){ printf("Content-Type:text/html;charset=ISO-8859-1\n\n"); char *p = NULL; int i_length = 0; char query_string[SIZE/2] = {0}; char *length = NULL; p = getenv("METHOD"); if (strcmp(p, "GET") == 0){ char *s = getenv("QESTRING"); memcpy(query_string, s, strlen(s)); }//if else{ length = getenv("Content-Length"); i_length = atoi(length); char ch = 0; for (int i = 0; i < i_length; i++){ ch = getc(0); query_string[i] = ch; } } hand(query_string); printf("\n"); return 0;}
mod表示操作,where是哪个·表,name是人名。
tbq这个表如下:
处理请求的结果:
前端知识知之甚少,勿怪啊。。
在这里一个简单的http服务器就搭建完成了,但是我们还可以做很多事。比如,当请求过多时效率太低怎么办?再者,我们可以写一个爬虫程序来提高。除此之外,我们可以在深入调研nginx服务器。
源码地址:https://github.com/fengasdf/-http-(由于整合了协程,python爬虫,以及其他程序,可能有点乱)
http服务器运用协程:
http://blog.csdn.net/fengasdfgh/article/details/76688440
阅读全文
0 0
- 搭建简单的http服务器
- 利用Socket搭建简单的Http服务器
- Python3.3搭建简单的HTTP服务器
- 搭建一个简单的http服务器
- Node.js学习-----------搭建一个简单的HTTP服务器
- 利用python搭建一个简单的http服务器
- Socket总结 & node搭建简单的http服务器
- 简单的http服务器
- 使用Python搭建简单Http服务器
- Apache http 服务器的搭建
- 用简单的方法实战演练搭建http服务器(Windows上)------专为http新手
- 用简单的方法实战演练搭建http服务器(Windows上)------专为http新手
- go语言 通过http包搭建简单web服务器 对http包源码的略微分析
- http服务-搭建简易的http服务器
- python 简单的Http服务器
- 一个简单的Http服务器
- 简单的http服务器源码
- 实现简单的HTTP服务器
- 【文献阅读】dropout distillation
- Vue进阶-入门
- Making the Grade (bzoj1592)
- unity角色摄像机实际坐标变了,但是不移动的问题
- 【Leetcode】【python】Binary Tree Preorder Traversal
- 搭建简单的http服务器
- 计算机视觉小实例 No.4 车牌定位(二)
- 08020000
- Spring日志记录+线程池
- python正则表达式
- 【Leetcode】【python】Binary Tree Postorder Traversal
- C++ 中为什么模板不支持分离编译?
- JSTL 标签详解
- 三目运算符