Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1029346
  • 博文数量: 177
  • 博客积分: 3629
  • 博客等级: 中校
  • 技术积分: 1839
  • 用 户 组: 普通用户
  • 注册时间: 2005-02-23 21:21
文章分类

全部博文(177)

文章存档

2021年(1)

2020年(5)

2019年(4)

2018年(7)

2017年(1)

2016年(4)

2014年(1)

2013年(8)

2012年(10)

2011年(50)

2009年(12)

2008年(10)

2006年(56)

2005年(8)

分类: C/C++

2006-04-10 15:07:07

有了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不知在这方面有多大的方便?
阅读(2122) | 评论(0) | 转发(0) |
0

上一篇:Socket库分析之五

下一篇:Socket库尝试之七

给主人留下些什么吧!~~