Cici 发表于 2009-8-31 07:21

纯C++的Socket访问Http封装类

1.项目中要使用c++++来访问Web服务器,从网上找了个C++的封装类,其中调用了MFC,在VC2005上用能用,但是移植到VC2003就出问题了,干脆修改成了纯C++的,不敢独享,share之。
2.以下是调用方法:

#include "stdafx.h"
#include <iostream> #include <string>
#include "http\request.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[]) {
    Request myRequest;      //初始化类   string sHeaderSend;   //定义http头
    string sHeaderReceive;//返回头   string sMessage="";   //返回页面内容
    bool IsPost=false;//是否Post提交
    int i =myRequest.SendRequest(IsPost, "http://neeao.com", sHeaderSend,
                                 sHeaderReceive, sMessage);   if (i)
    {            cout<<"Http头:"<<endl;
      cout<< sHeaderSend <<endl;         cout<<"响应头"<<endl;
      cout<< sHeaderReceive <<endl;         cout<<"网页内容"<<endl;
      cout<< sMessage <<endl;   }else
    {         cout<<"网络不可到达"<<endl;
    }   system("pause");
    return 0; }
直接上代码了,blog附件上传貌似有点问题,
Request.h

//******************************************
//纯C++的socket访问Http封装类,Neeao修改//http://neeao.com
//2009-08-25//******************************************
#if !defined(AFX_REQUEST_H__9F2C9BB6_CBA7_40AF_80A4_09A1CE1CE220__INCLUDED_)
#define AFX_REQUEST_H__9F2C9BB6_CBA7_40AF_80A4_09A1CE1CE220__INCLUDED_   
#if _MSC_VER > 1000#pragma once
#endif // _MSC_VER > 1000   
#include <stdio.h>
#include <stdlib.h>#include <string.h>
#include <winsock2.h>#pragma comment(lib, "WS2_32")   
using namespace std;
#define MEM_BUFFER_SIZE 10   
/*       HTTPRequest: Structure that returns the HTTP headers and message
                  from the request*/
typedef struct {   
    LPSTR headerSend;                               // Pointer to HTTP header Send       LPSTR headerReceive;                            // Pointer to HTTP headers Receive
    LPSTR message;                                  // Pointer to the HTTP message       long messageLength;                           // Length of the message   
} HTTPRequest;   
/*       MemBuffer:Structure used to implement a memory buffer, which is a
                buffer of memory that will grow to hold variable sized                  parts of the HTTP message.   
*/ typedef struct
{      unsigned    char *buffer;
    unsigned    char *position;      size_t      size;
} MemBuffer;   
class Request   
{public:
    Request();      virtual ~Request();
private:
    void      MemBufferCreate(MemBuffer *b);      void      MemBufferGrow(MemBuffer *b);
    void      MemBufferAddByte(MemBuffer *b, unsigned char byt);      void      MemBufferAddBuffer(MemBuffer *b, unsigned char *buffer, size_t size);
    DWORD       GetHostAddress(LPCSTR host);      void      SendString(SOCKET sock,LPCSTR str);
    BOOL      ValidHostChar(char ch);      void      ParseURL(string url,LPSTR protocol,int lprotocol, LPSTR host,int lhost,LPSTR request,int lrequest,int *port);
   int         SendHTTP(string url,LPCSTR headerReceive,BYTE *post, DWORD postLength,HTTPRequest *req);
public:
    int   SendRequest(bool IsPost, string url, string& psHeaderSend, string& pszHeaderReceive,string& pszMessage);};
#endif // !defined(AFX_REQUEST_H__9F2C9BB6_CBA7_40AF_80A4_09A1CE1CE220__INCLUDED_)
Request.cpp


//******************************************
//纯C++的Socket访问Http封装类,Neeao修改//http://neeao.com
//2009-08-25//******************************************

#include "stdafx.h"#include "Request.h"
#include <string>#ifdef _DEBUG
#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW#endif

//////////////////////////////////////////////////////////////////////// Construction/Destruction
//////////////////////////////////////////////////////////////////////   
Request::Request(){
}
Request::~Request()
{   
}   
//*******************************************************************************************************
//MemBufferCreate:   //                  Passed a MemBuffer structure, will allocate a memory buffer   
//                   of MEM_BUFFER_SIZE.This buffer can then grow as needed.//*******************************************************************************************************
void Request::MemBufferCreate(MemBuffer *b){
    b->size = MEM_BUFFER_SIZE;      b->buffer =(unsigned    char *) malloc( b->size );
    b->position = b->buffer;}
//*******************************************************************************************************
// MemBufferGrow:    //                  Double the size of the buffer that was passed to this function.   
//*******************************************************************************************************void Request::MemBufferGrow(MemBuffer *b)
{      size_t sz;
    sz = b->position - b->buffer;      b->size = b->size *2;
    b->buffer =(unsigned    char *) realloc(b->buffer,b->size);      b->position = b->buffer + sz;   // readjust current position
}   
//*******************************************************************************************************// MemBufferAddByte:   
//                  Add a single byte to the memory buffer, grow if needed.//*******************************************************************************************************
void Request::MemBufferAddByte(MemBuffer *b,unsigned char byt){
    if( (size_t)(b->position-b->buffer) >= b->size )          MemBufferGrow(b);
   *(b->position++) = byt;
}   
//*******************************************************************************************************// MemBufferAddBuffer:
//                  Add a range of bytes to the memory buffer, grow if needed.//*******************************************************************************************************
void Request::MemBufferAddBuffer(MemBuffer *b,                                 unsigned char *buffer, size_t size)
{      while( ((size_t)(b->position-b->buffer)+size) >= b->size )
      MemBufferGrow(b);   
    memcpy(b->position,buffer,size);      b->position+=size;
}   
//*******************************************************************************************************// GetHostAddress:   
//                  Resolve using DNS or similar(WINS,etc) the IP   //                   address for a domain name such as www.wdj.com.   
//*******************************************************************************************************DWORD Request::GetHostAddress(LPCSTR host)
{      struct hostent *phe;
    char *p;   
    phe = gethostbyname( host );   
    if(phe==NULL)          return 0;
   p = *phe->h_addr_list;
    return *((DWORD*)p);}
//*******************************************************************************************************
// SendString:   //                  Send a string(null terminated) over the specified socket.
//*******************************************************************************************************void Request::SendString(SOCKET sock,LPCSTR str)
{      send(sock,str,strlen(str),0);
}   
//*******************************************************************************************************// ValidHostChar:   
//                  Return TRUE if the specified character is valid//                      for a host name, i.e. A-Z or 0-9 or -.:   
//*******************************************************************************************************BOOL Request::ValidHostChar(char ch)
{      return( isalpha(ch) || isdigit(ch)
      || ch=='-' || ch=='.' || ch==':' );}

//*******************************************************************************************************// ParseURL:   
//                  Used to break apart a URL such as   //                      http://www.localhost.com:80/TestPost.htm into protocol, port, host and request.
//*******************************************************************************************************void Request::ParseURL(string url,LPSTR protocol,int lprotocol,LPSTR host,int lhost,LPSTR request,int lrequest,int *port)
{      char *work,*ptr,*ptr2;
   *protocol = *host = *request = 0;
    *port=80;   
    work = strdup(url.c_str());      strupr(work);
   ptr = strchr(work,':');                         // find protocol if any
    if(ptr!=NULL)      {
      *(ptr++) = 0;          lstrcpyn(protocol,work,lprotocol);
    }      else
    {          lstrcpyn(protocol,"HTTP",lprotocol);
      ptr = work;      }
   if( (*ptr=='/') && (*(ptr+1)=='/') )            // skip past opening /'s   
      ptr+=2;   
    ptr2 = ptr;                                     // find host      while( ValidHostChar(*ptr2) && *ptr2 )
      ptr2++;   
    *ptr2=0;      lstrcpyn(host,ptr,lhost);
   lstrcpyn(request,url.c_str() + (ptr2-work),lrequest);   // find the request
   ptr = strchr(host,':');                         // find the port number, if any
    if(ptr!=NULL)      {
      *ptr=0;          *port = atoi(ptr+1);
    }   
    free(work);}
//*******************************************************************************************************
// SendHTTP:   //                  Main entry point for this code.   
//                  url         - The URL to GET/POST to/from.//                  headerSend      - Headers to be sent to the server.
//                  post          - Data to be posted to the server, NULL if GET.//                  postLength    - Length of data to post.
//                  req         - Contains the message and headerSend sent by the server.//
//                  returns 1 on failure, 0 on success.//*******************************************************************************************************
int Request::SendHTTP(string url,LPCSTR headerReceive,BYTE *post,                        DWORD postLength,HTTPRequest *req)
{      WSADATA         WsaData;
    SOCKADDR_IN   sin;      SOCKET          sock;
    char            buffer;      char            protocol,host,request;
    int             l,port,chars,err;      MemBuffer       headersBuffer,messageBuffer;
    char            headerSend;      BOOL            done;


    ParseURL(url,protocol,sizeof(protocol),host,sizeof(host),       // Parse the URL          request,sizeof(request),&port);
    if(strcmp(protocol,"HTTP"))          return 1;
   err = WSAStartup (0x0101, &WsaData);                            // Init Winsock
    if(err!=0)          return 1;
   sock = socket (AF_INET, SOCK_STREAM, 0);
    //if (socket == INVALID_SOCKET)      if (sock == INVALID_SOCKET)
    {          return 1;
    }   
    sin.sin_family = AF_INET;                                       //Connect to web sever      sin.sin_port = htons( (unsigned short)port );
    sin.sin_addr.s_addr = GetHostAddress(host);   
    if( connect (sock,(LPSOCKADDR)&sin, sizeof(SOCKADDR_IN) ) )      {
         return 1;
    }   
   if( !*request )
      lstrcpyn(request,"/",sizeof(request));   
    if( post == NULL )      {
      SendString(sock,"GET ");          strcpy(headerSend, "GET ");
    }      else   
    {          SendString(sock,"POST ");
      strcpy(headerSend, "POST ");      }
    SendString(sock,request);      strcat(headerSend, request);
   SendString(sock," HTTP/1.0\r\n");
    strcat(headerSend, " HTTP/1.0\r\n");   
    SendString(sock,"Accept: image/gif, image/x-xbitmap,"         " image/jpeg, image/pjpeg, application/vnd.ms-excel,"
      " application/msword, application/vnd.ms-powerpoint,"         " */*\r\n");
    strcat(headerSend, "Accept: image/gif, image/x-xbitmap,"         " image/jpeg, image/pjpeg, application/vnd.ms-excel,"
      " application/msword, application/vnd.ms-powerpoint,"         " */*\r\n");
   SendString(sock,"Accept-Language: en-us\r\n");
    strcat(headerSend, "Accept-Language: en-us\r\n");   
    SendString(sock,"Accept-Encoding: gzip, default\r\n");      strcat(headerSend, "Accept-Encoding: gzip, default\r\n");
   SendString(sock,"User-Agent: Neeao/4.0\r\n");
    strcat(headerSend, "User-Agent: Neeao/4.0\r\n");   
    if(postLength)      {
      sprintf(buffer,"Content-Length: %ld\r\n",postLength);          SendString(sock,buffer);
      strcat(headerSend, buffer);      }
    //SendString(sock,"Cookie: mycookie=blablabla\r\n");      //printf("Cookie: mycookie=blablabla\r\n");
    SendString(sock,"Host: ");      strcat(headerSend, "Host: ");
   SendString(sock,host);
    strcat(headerSend, host);   
    SendString(sock,"\r\n");      strcat(headerSend, "\r\n");
   if( (headerReceive!=NULL) && *headerReceive )
    {          SendString(sock,headerReceive);
      strcat(headerSend, headerReceive);      }
   SendString(sock,"\r\n");                              // Send a blank line to signal end of HTTP headerReceive
    strcat(headerSend, "\r\n");   
    if( (post!=NULL) && postLength )      {
      send(sock,(const char*)post,postLength,0);          post    = '\0';
         strcat(headerSend, (const char*)post);
    }   
    //strcpy(req->headerSend, headerSend);      req->headerSend   = (char*) malloc( sizeof(char*) * strlen(headerSend));
    strcpy(req->headerSend, (char*) headerSend );   
   MemBufferCreate(&headersBuffer );
    chars = 0;      done = FALSE;
   while(!done)
    {          l = recv(sock,buffer,1,0);
      if(l<0)            done=TRUE;
         switch(*buffer)
      {          case '\r':
            break;          case '\n':
            if(chars==0)                  done = TRUE;
            chars=0;            break;
      default:            chars++;
            break;          }
         MemBufferAddByte(&headersBuffer,*buffer);
    }   
    req->headerReceive= (char*) headersBuffer.buffer;      *(headersBuffer.position) = 0;

   MemBufferCreate(&messageBuffer);                            // Now read the HTTP body
   do
    {          l = recv(sock,buffer,sizeof(buffer)-1,0);
      if(l<0)            break;
      *(buffer+l)=0;          MemBufferAddBuffer(&messageBuffer, (unsigned char*)&buffer, l);
    } while(l>0);      *messageBuffer.position = 0;
    req->message = (char*) messageBuffer.buffer;      req->messageLength = (messageBuffer.position - messageBuffer.buffer);

    closesocket(sock);                                          // Cleanup   
    return 0;}

//*******************************************************************************************************// SendRequest
////*******************************************************************************************************
int Request::SendRequest(bool IsPost, string url, string& psHeaderSend, string& psHeaderReceive, string& psMessage){
    HTTPRequest         req;      int               i,rtn;
    LPSTR               buffer;   
    req.headerSend                        = NULL;      req.headerReceive                     = NULL;
    req.message                           = NULL;   
    //Read in arguments   
   if(IsPost)
    {                                                   /* POST */          i       = psHeaderSend.length();
      buffer= (char*) malloc(i+1);          strcpy(buffer, psHeaderSend.c_str());
         rtn             = SendHTTP( url,
            "Content-Type: application/x-www-form-urlencoded\r\n",            (unsigned char*)buffer,
            i,            &req);
         free(buffer);
    }      else/* GET */
    {          rtn = SendHTTP(url,NULL,NULL,0,&req);
    }   

    if(!rtn)                                          //Output message and/or headerSend       {
      psHeaderSend      = req.headerSend;          psHeaderReceive   = req.headerReceive;
      psMessage         = req.message;   
         free(req.headerSend);
      free(req.headerReceive);          free(req.message);
      return 1;      }
    else   {
      return 0;      }
}

reckless 发表于 2009-8-31 12:01

能打包上传一下吗

wangfakun 发表于 2009-8-31 12:33

LZa啊 .发的代码有些乱.能稍微整理下么

zapline 发表于 2009-8-31 19:08

汗 太乱了
把.H和.CPP文件打包发上来吧
页: [1]
查看完整版本: 纯C++的Socket访问Http封装类