HTTP服务器实现文件上传与下载
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
怎么样,第三方商业库的基本原理还是一致的,只是他们对其进行了优化而已。在开始的编
写时,我不会全部的简介 Http 的协议的内容,这样太枯燥了,我仅仅解释一些下面需要用
到的协议字段。
在写本文的时候,之前也有些迷惑,C++到底能干啥,到网上一搜,无非就是能开发游戏,
嵌入式编程,写服务器等等。接着如果问如何编写一个服务器的话,那么这些网络水人又会
短的几行代码,要么就是加入了微软的一些 C#内容或者 MFC,这些在我看来只是一些无关
紧要的东西,加入后或许界面上你很舒服,但是大大增加了我们的学习成本,因为这些界面
上的代码改变了我们所知道的程序流程走向,还有一些界面代码和核心代码的混合,非常不
利于学习。
二、HTTP 协议
在大家在浏览器的 url 输入栏上输入 http://10.1.18.4/doing 时。浏览器向 10.1.18.4 服务器 80
9 Host: 10.1.18.4\r\n\
10 User-Agent: Mozilla/5.0 (Windows NT 6.2; rv:40.0) Gecko/20100101
Firefox/40.0\r\n\
11
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,*//*;q=0.8\ r\n\ 12 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3\r\n\ 13 Accept-Encoding: gzip, deflate\r\n\ 14 Referer: http:http://10.1.18.4/\r\n\ 15 Connection: keep-alive\r\n\ 16 Range: bytes=14584264-\r\n\r\n" ; 17 18 string& ltrim(string &str) { 19 string::iterator p = find_if(str.begin(), str.end(), not1(ptr_fun 20 str.erase(str.begin(), p); 21 return str; 22 } 23 24 string& rtrim(string &str) { 25 string::reverse_iterator p = find_if(str.rbegin(), str.rend(), not1(ptr_fun(isspace))); 26 str.erase(p.base(), str.end()); 27 return str; 28 } 29 30 string& trim(string &str) { 31 ltrim(rtrim(str)); 32 return str; 33 } 34 string getContent(string& str,int start,char c,int &pos){ 35 int i=start; 36 int len=str.size(); 37 while(i 38 i++; 39 } 40 pos=i; 41 return str.substr(start,i-start); 42 } 43 map 44 int len=strlen(str); 45 vector vs; 46 int i=0; 47 while(i 48 if(str[i]!='\r'){ 49 int j=i; 50 while(i 51 i++; 52 vs.push_back(string(str+j,str+i));
可以自己百度。
5)以下的一些信息中,没有什么用到,我就不解释,看文本意义也大概知道一些信息。详细
的请搜索网络。
在最重要的是一本请求头什么时候表示结束呢,那就是一个空行表示结束。其实就是"\r\n"
结束。
说了这么多可能大家还是有点迷糊,知道这些那么在程序中又是怎么实现的呢。当初我也迷
惑,现在我提出一个最简单的一种实现,就是直接连接一个字符串即可。在实际实现中我对
端口的进程发送了如下的一个协议头,它是一个文本字符串。每行以\r\n 结束。表示回车换
行。
1 GET /doing HTTP/1.1
2 Host: 10.1.18.4
3 User-Agent: Mozilla/5.0 (Windows NT 6.2; rv:40.0) Gecko/20100101
Firefox/40.0
7 Referer: http://10.1.18.4/\r\n\
8 Connection: keep-alive\r\n\
9 Range: bytes=14584264-\r\n\r\n" ;
可能上面的协议内容跟之前的有点不一样,没关系,我只是截取了一些内容进行输入。很简
单就是 C 语言的 char*字符串。在没一行的的结尾都都有一个'\',表示表示换行输入,去掉
也行,需要把器内容写到一行上,是 C 语言语法,不懂的读者可以自己查阅 C 语言的字符
串。我想说的是在每行的结尾都有一个\r\n。这两个转义字符就是代表回车换行。并且在第
9 行有 2 个\r\n,最后一个代表着空行,意思是说告诉服务器我的协议头到此位置。
为什么需要一个空行呢,这里就有一个网络编程的小小信息。在 socket TCP 流编程中,比如
然后对其进行解析。下面就是解析这段字符串的代码,在工程中我对其封装,但是现在我们
只要知道实现解析功能即可。
1 #include
2 #include
3 #include
4 #include
5 #include
6 using namespace std;
7
8 char *str= "GET /download/JBPM4S.tt HTTP/1.1\r\n\
4
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,*//*;q=0.8\
r\n\
5 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3\r\n\
6 Accept-Encoding: gzip, deflate\r\n\
高效和设计一个框架都是非常困难的一件事情。但这些事情 Java 已经在底层为我们封装好
了,而我们仅仅只是在做业务层上的事情吧了。
在本 Http 服务器实现中,利用 C++库和 socket 原套接字编程和 pthread 线程编写。拒绝使用
Biblioteka Baidu
第三方库。因为主要是让大家知道基本的实现方式,除去一些安全、高效等特性,但是不管
7 Referer: http://10.1.18.4/
8 Connection: keep-alive
所以知道其实我们发送了一个 URL 请求,其实被转化为了一个如上的一些字符串。在这里
我简单的解释一下这个协议头表示什么,因为在网上你可以找到非常多的信息来解释它们。
1)第一行中 GET /doing HTTP1.1 表示请求的方式是 GET,URL 是/doing ,HTTP 协议的版本是 1.1
Http 服务器实现文件上传与下载(一)
一、引言
大家都知道 web 编程的协议就是 http 协议,称为超文本传输协议。在 J2EE 中我们可以很快
的实现一个 Web 工程,但在 C++中就不是非常的迅速,原因无非就是底层的 socket 网络编
写需要自己完成,上层的 http 协议需要我们自己完成,用户接口需要我们自己完成,如何
HTTP 网络协议中的 HTTP Client Hints 技术 一些安全相关的 HTTP 响应头 漫谈:HTTP 网络协议中 Vary 响应头 漫谈:Http 网络协议中的 Proxy-Connection 漫谈:Http 网络协议中的 X-Forwarded-For
53 }else{ 54 i+=2; 55 } 56 } 57 int pos; 58 string method=getContent(vs[0],0,' ',pos); 59 string url=getContent(vs[0],method.size()+1,' ',pos); 60 map 61 mp["Method"]=method; 62 mp["Url"]=url; 63 for(int i=1;i 64 string key=getContent(vs[i],0,':',pos); 65 string value=vs[i].substr(pos+1); 66 mp[key]=trim(value); 67 } 68 return mp; 69 } 70 71 int main(int argc, char **argv) 72 { 73 map 74 for(map 75 cout< 76 } 77 return 0; 78 } 把一些信息解析都放到了一个 map 里面。这里的解析是先处理每一行,然后再对每一行进 行解析。可能这样的处理方式有点慢,但是没什么关系,原因是字符串反正比较短,在大并 发下效率不会影响太大,如果大家有什么更好的解析方式,可以回复我。 在服务端解析头信息后,我们可以得到/doing 这个 url,这样我们服务请就可以把客户端需 要的内容返回给客户端了,这里就有浏览器请求的内容是否合法是否存在这些信息。就要在 相应的响应头中说明,在《Http 服务器实现文件上传与下载(二)》中会进行说明。 欢迎大家一起探讨这些问题。有什么想法的人给我回复,我们一起学习,一起进步哦。 【编辑推荐】
4
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
6 Accept-Encoding: gzip, deflate
2)第二行中 Host 就是服务器的 IP
3)第三行中 User-Agent 代表着你使用的是什么浏览器在什么系统上运行的。从上本可以这
条信息显示是 window 上火狐浏览器发出的请求头
4)第四行中 Accept 代表着该浏览器可以接受的信息格式,可以是文本,html,或者应用文件
(二进制文件)。其中 q 代表权重,表示更愿意接受前面的信息。还有一些其他的内容,读者
你调用了 write 或 read 函数,内部不是一次性接受或者发送所有的信息。所以当我们发送上
述的 str 的时候,不一定一次全部的发送,那么服务端就不知道什么时候结尾了。所以我们
需要 HTTP 规定以空行作为结尾代表着协议头的结束。
接下面了来就是我们编写的服务器接受到这个字符串。并且以空行表示接受到整个协议头,
告诉你,你先把基础学好,看看什么书,之后你就知道了,我只能呵呵了,在无目的的学习
中,尽管看了你也不知道如何写的,因为尽管你知道一些大概,但是没有一个人领导你入门,
我们还是无法编写一个我们自己想要的东西,我写这篇博客主要是做一个小小的敲门砖吧,
尽管网上有许多博客,关于如何编写 HTTP 服务器的,但是要不是第三方库 acl,要么就是短
其进行了分解,但是现在,我解释为如下编写程序:
1 char *str= "GET /doing HTTP/1.1\r\n\
2 Host: 10.1.18.4\r\n\
3 User-Agent: Mozilla/5.0 (Windows NT 6.2; rv:40.0) Gecko/20100101
Firefox/40.0\r\n\