HTTP server implementation file upload and download (iv)

Source: Internet
Author: User
Tags sendfile

First, Introduction

Welcome everyone to join me to write an HTTP server implementation file upload and download, and now I have a little review of the previous I said, the first to second chapter explains the overall HTTP trend, the third chapter to achieve the bottom of the network programming. And then this chapter I want to tell you is the request to get, and the response to send the content. Here is the main explanation of the response content, why? Because we are writing an HTTP server that interacts with the browser, in most cases we only respond passively.

This is a question of "question-answer". In fact, when explaining this chapter, I was prepared to explain some of the problems of Linux signal interruption. Because when the network layer is sent, the system will send some signals to our application, so it will cause our program to terminate unexpectedly. But when I wrote this blog I gave up, I want to talk about the flow of the time to mention an interrupt capture it. In this request response layer class actually the design needs a lot of content, here is the HttpResponse class and the HttpRequest class design, in the Java EE, we write the servlet when we use these 2 classes, such as Httpservletresquest, HttpServletResponse class, if you are interested in this content, you can download Tomcat, there are these classes in the Servlet-api.jar package.

In the implementation of this article, the request class contains only a few methods to get the request header and the parsing header. How to parse the header, I in the "HTTP Server implementation file upload and download (a)" has been explained, the reader only need to encapsulate a class.

Second, HttpRequest class

The parsing of the request message is through a class named HttpRequest that is defined in the namespace HTTP. The constructor for this class accepts a socket, which is the socket that we are connecting to, which we have already talked about in the network layer, and then calls Server_read () in the GetHeader method to get the request header, and then parses it through the Utils::p arseheader () function. This puts the parsed content into the required string, which is not currently needed directly in the map. Here I put the code directly, and everyone seems to be relatively easy. Here I am in this chapter mainly on the download of the file, so the main analysis of the HttpResponse class, and the HttpRequest class only paste the content that is currently needed.

Header file (include/httprequest.h)

1 #ifndef httprequest_h 2 #define HTTPREQUEST_H 3 #include "socket.h" 4 #include <map> 5 #include <string> 6 # Include <fstream> 7 namespace http{8     class httprequest{9         public:10             HttpRequest (tcp::socket &c) ; one             virtual ~httprequest ();             std::map<std::string,std::string>  getheader (int confd)             ; ......         protected:15         private:16             std::string method;17             std::string url;18             std::string host;19             tcp::socket &s;20     }; }22 #endif//Httprequest_h

source file (Src/httprequest.cpp)

1 #include "httprequest.h" 2 #include "utils.h" 3 namespace http{4     httprequest::httprequest (Tcp::socket &c): s (c ) {5     } 6  7     httprequest::~httprequest () {8     } 9     std::map<std::string,std::string> Httprequest::getheader (int confd) {Ten         char recvbuf[1024];11         memset (recvbuf,0,sizeof (RECVBUF));         S.server_read (confd,recvbuf,1024);         std::cout<<recvbuf<<std::endl;14         std::map<std:: String,std::string> MP =utils::p Arseheader (RECVBUF);         method =mp["method"];16         url=mp["url"];17         host=mp["host"];18         return mp;19     }20     ... 21}

Third, HttpResponse class

  When we visit the HTTP server, the browser displays the contents of the file that can be downloaded, and then we click on the file that needs to be downloaded, and then the file is available for download. First I click this URL of this file, the browser sends us some request headers, for example it sends a URL for/download/httpserver.zip, stating that he needs to download the file, and that the file is Httpserver.zip. Above we can already use GetHeader to capture this request header, and then get the URL. After the server is still sending a response header, tell the browser your request we agree, the request header ends with an empty behavior tag, followed by the content of the specific file.

When sending the response header, still need to send protocol version, status code, Response content type, file length, file breakpoint download and other content, or transfer with chunk transmission, but here I use the length of the file to mark. Readers can view other ways of transmitting content themselves. It's important to note that Ed is sure to specify the size of the transport entity in the response header, or the client does not know when to end, and may refuse to receive bytes from the server. In this class, I use the Sendfile function when a file is requested for download, and the function reads the file in a binary way, and in the response header tells the browser to receive the file in a binary way. This is a binary way to read and send files before the problem occurs. Sendlinefile and Sendindexfile are roughly the same, both of which use ASCII text to send content, such as HTML that needs to be displayed in the browser's content, through these two functions. The function name indicates that the Sendlinefile is read as a file line, and the Sendindexfile file writes the contents on the same line. For example: Our browser request a index.html content, when using 2 Sendlinefile and sendindexfile display effect is the same, but if right click to view the source code, Sendlinefile content is the same as the source file, and Sendindexfile The content sent will be in the first line and will not be wrapped.

Said so many people are more clear, the following post specific code.

Header file (include/httpresponse.h)

 1 #ifndef httpresponse_h 2 #define HTTPRESPONSE_H 3 #include "socket.h" 4 #include <string> 5 #include <fstream&gt ; 6 #include <sstream> 7 #include <iterator> 8 #include <algorithm> 9 #include <time.h>10 #include " Utils.h "namespace Http{12 class httpresponse{13 public:14 HttpResponse (Tcp::socket &c); Irtual ~httpresponse (); ssize_t Send (int confd,std::string content); ssize_t sendindexfile (int confd,s Td::string FileName); ssize_t sendFile (int &confd,std::string filename,int64_t POS); ssize_t Sendl          Inefile (int confd,std::string file), void Setprotocal (std::string), Setstatuscode (std::string); 22 void Setservername (std::string), setContentType (std::string), void Setcontentrange (std:: string); Setcontentlength (int64_t); protected:27 std::string GetHeader () const;28 Private : std::string PRotocal;30 std::string statuscode;31 std::string servername;32 std::string contenttype;33 s Td::string contentlength;34 std::string contentrange;35 std::string connection;36 std::string Date ; PNs tcp::socket &s;38};39}40 #endif//Httpresponse_h

source file (src/httpresponse.cpp)

  1 #include "httpresponse.h" 2 namespace http{3 Httpresponse::httpresponse (Tcp::socket &c): s (c) {4  Protocal= "http/1.1";  5 statuscode= "OK";  6 Servername= "Server: (Unix)";  7 contenttype= "content-type:text/html";  8 contentlength= "content-length:0"; 9 contentrange= "content-range:0-"; Ten connection= "connection:keep-alive"; One by one time_t TIMEP; (&AMP;TIMEP); -Char s[50]; sprintf (S,ctime (&AMP;TIMEP)); date= "Date:" +std::string (s,s+ (strlen (s)-1));          Httpresponse::~httpresponse () {21} httpresponse::setprotocal (std::string content) Protocal=content;  \ httpresponse::setstatuscode (std::string content) {statuscode=content; Httpresponse::setservername (std::string content) {servername=content;) void Httpresponse::setco Ntenttype (std::string Content) {contenttype= "content-type:" +content; Httpresponse::setcontentlength (int64_t len) {contentlength= "content-length:" +utils::tostri Ng (Len);  Httpresponse::setcontentrange} (std::string content) {contentrange= "content-range:" +content; Panax std::string httpresponse::getheader () const{std::string H1 =protocal+ "" +statuscode+ "\ r \ n"; 4 0 std::string H2 =servername+ "\ r \ n"; std::string h3 =contenttype+ "\ r \ n"; std::string h4 =contentlength+ "\ r \ n"; std::string h5=contentrange+ "\ r \ n"; std::string h6=connection+ "\ r \ n"; std::string h7=date+ "\r\n\r\n"; H1+h2+h3+h4+h5+h6+h7 return; ssize_t httpresponse::send (int confd,std::string content) {setContentType ("application/octet-st Ream "); Setcontentlength (Content.size ()); Wuyi std::string Header=getheader (); S.server_write (CONFD, (char*) Header.c_str (), header.size ()); ssize_t Len =s.server_write (CONFD, (char*) content.c_str (), content.size ()); S.server_close (CONFD); return Len;  ssize_t httpresponse::sendlinefile (int confd,std::string file) {Std::ifstream in (File.c_str ()); IN.SEEKG (0,std::ios::end); int64_t len = In.tellg (); Setcontentlength (len); std::string Header=getheader (); S.server_write (CONFD, (char*) header.c_str (), header.size ()); IN.SEEKG (0,std::ios::beg); ssize_t n=0; buf[1024 Char]; while (!in.eof ()) {bzero (buf,sizeof (BUF)); In.getline (buf,1024); F[strlen (buf)]= ' \ n '; N+=s.server_write (Confd,buf,in.gcount ()); S.server_close (CONFD); The return n; ssize_t httpresponse::sendindexfile (int confd,std::string file) {Std::ifstream in (file.c_str()); IN.SEEKG (0,std::ios::end); int64_t len = In.tellg (); Setcontentlength (len); Bayi std::string Header=getheader (); S.server_write (CONFD, (char*) header.c_str (), header.size ()); IN.SEEKG (0,std::ios::beg); buf[1024 Char]; sendcount=0 int;             (!in.eof ()) {memset (buf,0,sizeof (BUF)); In.getline (buf,1024); 89 Sendcount+=s.server_write (Confd,buf,in.gcount ()); S.server_close (CONFD); Sendcount return; 94 ssize_t httpresponse::sendfile (int &confd,std::string filename,int64_t POS) {Std::ifstream In (Filename.c_str (), std::ios::binary); IN.SEEKG (0, Std::ios::end); Std::streampos PS = In.tellg (); 98 int64_t Len=ps-pos; if (pos!=0) {Setstatuscode ("206 Partial Content") 101}102 setcontenttype ("Applic Ation/octet-stream "); 103 sEtcontentlength (len); 104 std::string content= "bytes"; content+= "" +utils::tostring (POS) + "-" +utils::tost Ring ((int64_t) ps-1) + "/" +utils::tostring (len); 106 Setcontentrange (content); 107 std::string Header=getheader (); 108 std::cout<

In the above response header content-range: This field, which represents the range of file contents, is generally from 0 to lenth (file)-1. If something has been done before, if a breakpoint continues to download, the browser has a range in the request header, indicating that the transfer from the start byte of range, and our server specifies content-range to start the Range field, and then send the content to implement the file breakpoint download. Next, please see "HTTP Server implementation file upload and download (v)".

HTTP server implementation file upload and download (iv)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.