有了Socket和TcpSocket,SocketHandle三个类的基础,这个HttpSocket类就很简单了,不过它是HttpGetSocket,HttpPostGetSocket的基类,着实得看看它.才好使用它.
类代码不长,偶加了说明,罗列如下:
class HTTPSocket : public TcpSocket
{
/** map to hold http header values. */
typedef std::map string_m;
public:
HTTPSocket(SocketHandler& );
~HTTPSocket();
void OnRead(); //和下面两个有个共性,都是从Socket类过来的虚函数重载
void ReadLine(); //调用OnLine
void OnLine(const std::string& line); //处理每一行的HTTP命令
/*只在第一次接收到第一行http头信息时.此函数体里可调用 GetMethod, GetUrl/GetUri, and GetHttpVersion*/
virtual void OnFirst() = 0;
/*Http头是以 CRLF做为行结束标志,每收到一行就会调用OnHeader,可以在这儿找到头信息.
\param key Http header name
\param value Http header value */
virtual void OnHeader(const std::string& key,const std::string& value) = 0;
/*当http头信息已经全部接收完时(不含实体),调用*/
virtual void OnHeaderComplete() = 0;
/** Chunk of http body data recevied. 这儿接收HTTP头的实体部分*/
virtual void OnData(const char *,size_t) = 0;
const std::string& GetMethod();
void SetMethod(const std::string& x);
const std::string& GetUrl();
void SetUrl(const std::string& x);
const std::string& GetUri();
void SetUri(const std::string& x);
const std::string& GetQueryString();
const std::string& GetHttpVersion();
const std::string& GetStatus();
const std::string& GetStatusText();
bool IsRequest();
bool IsResponse();
void SetHttpVersion(const std::string& x);
void SetStatus(const std::string& x);
void SetStatusText(const std::string& x);
void AddResponseHeader(const std::string& x,const std::string& y);
void AddResponseHeader(const std::string& x,char *format, ...);
void SendResponse();
void SendRequest();
/** Implement this to return your own User-agent string. */
virtual std::string MyUseragent();
protected:
HTTPSocket(const HTTPSocket& s) : TcpSocket(s) {}
/** Reset state of socket to sucessfully implement keep-alive. */
virtual void Reset();
private:
HTTPSocket& operator=(const HTTPSocket& ) { return *this; }
bool m_first;
bool m_header;
std::string m_line;
std::string m_method;
std::string m_url;
std::string m_uri;
std::string m_query_string;
std::string m_http_version;
std::string m_status;
std::string m_status_text;
bool m_request;
bool m_response;
string_m m_response_header;
};
看构造函数:
HTTPSocket::HTTPSocket(SocketHandler& h)
:TcpSocket(h)
,m_first(true)
,m_header(true)
,m_http_version("HTTP/1.0")
,m_request(false)
,m_response(false)
{
SetLineProtocol();
}
这一行SetLineProtocol决定当SocketHandler::Select()开始时会调用Socket::ReadLine,ReadLine-->OnLine-->OnFirst,OnHeader,OnHeaderComplete.
上面处理的都是头信息,没有实体的部分,因为实体是关键,所以特有一个专职回调函数:OnData()处理它,只需要重载它,就可以处理数据.保证不含头信息.这一点比TcpSocket方便一些.
下面是偶的示例代码.
#include
#include
#include
using namespace std;
class MyHttp : public HTTPSocket
{
public:
MyHttp(SocketHandler& h): HTTPSocket(h) {}
void OnData(const char *,size_t);
void OnHeader(const std::string& key,const std::string& value);
void OnHeaderComplete();
void OnFirst();
void OnConnect();
};
void MyHttp::OnData(const char *p,size_t size)
{
//得到http头的实体部分,这儿是百度首页
string tmp(p,size);
cout<}
void MyHttp::OnHeader(const std::string& key,const std::string& value)
{
//Http头是以 CRLF做为行结束标志,每收到一行就会调用OnHeader,可以在这儿找到头信息.
cout<<"MyHttp::OnHeader"<}
void MyHttp::OnHeaderComplete()
{
//收到的http头信息已经全部接收完时,调用...
cout<<"MyHttp::OnHeaderComplete"<}
void MyHttp::OnFirst()
{
//只在第一次接收到一行http头信息时.
cout<<"MyHttp::OnFirst"<}
void MyHttp::OnConnect()
{
//HttpSocket类还是需要在这里发送自己的命令
SendRequest();
}
int main()
{
SocketHandler h;
MyHttp Get(h);
Get.SetHttpVersion("HTTP/1.1");
Get.SetMethod("GET");
Get.SetUrl("/");
Get.AddResponseHeader("HOST","");
Get.Open(");
h.Add(&Get);
h.Select(1,0);
while(h.GetCount()){
h.Select(1,0);
}
}
AddResponseHeader()函数有点迷惑人,不过只要是HTTP头都可以用它构造,不只限于Response,Request当然也可以.
提醒一下:
可以用Parse类处理像
这样的URL.下面的HttpGetSocket不知在这方面有多大的方便?
阅读(2129) | 评论(0) | 转发(0) |