C++ 用socket封装成http

// Http.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "HttpSocket.h"

int main(int argc, char* argv[])
{
 //TRACE("Hello World!\n");

    char szPath[256] = "\0";
    GetCurrentDirectory(256,szPath);
    strcat(szPath,"\\Archive");
    char strFilePath[256] = "\0";
    wsprintf(strFilePath,"%s.htm",szPath);
 
    CHttpSocket HttpSocket;
   // CString strServer,strObject;

    unsigned short nPort=80;
    DWORD dwServiceType=AFX_INET_SERVICE_HTTP;
    long nLength;
    const char *pRequestHeader = NULL;
    //AfxParseURL("http://www.jtytoys.com/zhang/inc/tail1.asp",dwServiceType,strServer,strObject,nPort);
   
    //pRequestHeader = HttpSocket.FormatRequestHeader((LPTSTR)(LPCTSTR)strServer,(LPTSTR)(LPCTSTR)strObject,nLength);   
    pRequestHeader = HttpSocket.FormatRequestHeader("www.jtytoys.com",nPort))
    {
        TRACE("连接服务器出错/n");
        return -1;
    }
   
    if(!HttpSocket.SendRequest())
    {
        TRACE("发送请求出错/n");

        return -1;
    }
   
   
    int nLineSize = 0;
    char szValue[30];
    HttpSocket.GetField("Content-Length",szValue,30);
    int nSvrState = HttpSocket.GetServerState();
   
    //服务器状态
    if(nSvrState == 404)
    {

        return -1;
    }
   
    int nFileSize = atoi(szValue);//URL文件的长度
    int nCompletedSize = 0;
    CFile File;
    File.Open(strFilePath,CFile::modeCreate | CFile::modeWrite);
    char pData[1024];
    int nReceSize = 0;
    DWORD dwStartTime,dwEndTime;
    while(nCompletedSize < nFileSize)
    {
        dwStartTime = GetTickCount();
        nReceSize = HttpSocket.Receive(pData,1024);
        if(nReceSize == 0)
        {
            TRACE("服务器已经关闭连接/n");

            return -1;
        }
        if(nReceSize == -1)
        {
            TRACE("接收数据超时./n");

            return -1;
        }
        dwEndTime = GetTickCount();
        File.Write(pData,nReceSize);
        nCompletedSize += nReceSize;
    }
    File.Close();


 return 0;
}

 

 

 

// HttpSocket.h: interface for the CHttpSocket class.
//
//
#include "stdafx.h"
#if !defined(AFX_HTTPSOCKET_H__F49A8F82_A933_41A8_AF47_68FBCAC4ADA6__INCLUDED_)
#define AFX_HTTPSOCKET_H__F49A8F82_A933_41A8_AF47_68FBCAC4ADA6__INCLUDED_

#include <afxinet.h>
#include <Winsock2.h>

#pragma comment(lib,"Ws2_32")

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CHttpSocket 
{
public:
    CHttpSocket();
    virtual ~CHttpSocket();
    int    GetServerState();//返回服务器状态码 -1表示不成功
    int    GetField(const char* szSession,char *szValue,int nMaxLength);//返回某个域值,-1表示不成功
    int    GetResponseLine(char *pLine,int nMaxLength);//获取返回头的一行
    const char*    GetResponseHeader(int &Length);//获取完整的返回头
    const char *FormatRequestHeader(char *pServer,char *pObject,long &Length,
                        char* pCookie=NULL,char *pReferer=NULL,
                        long nFrom=0,long nTo=0,
                        int nServerType=0);//格式化请求头
    int    GetRequestHeader(char *pHeader,int nMaxLength) const;
    BOOL SendRequest(const char* pRequestHeader = NULL,long Length = 0);   
    BOOL SetTimeout(int nTime,int nType=0);
    long Receive(char* pBuffer,long nMaxLength);
    BOOL Connect(char* szHostName,int nPort=80);
    BOOL Socket();
    BOOL CloseSocket();
protected:   
    char m_requestheader[1024];        //请求头
    char m_ResponseHeader[1024];    //回应头
    int m_port;                        //端口
    char m_ipaddr[256];                //IP地址
    BOOL m_bConnected;
    SOCKET m_s;
    hostent *m_phostent;

    int m_nCurIndex;                //GetResponsLine()函数的游标记录
    BOOL m_bResponsed;                //是否已经取得了返回头
    int m_nResponseHeaderSize;        //回应头的大小
};

#endif // !defined(AFX_HTTPSOCKET_H__F49A8F82_A933_41A8_AF47_68FBCAC4ADA6__INCLUDED_)

 

 

 

 

 

 

// HttpSocket.cpp: implementation of the CHttpSocket class.
//
//

#include "stdafx.h"
#include "HttpSocket.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define MAXHEADERSIZE 1024

int FindPos(const char * res,const char *dest,int sta=0)
{
 int nPos = -1;
 //   nPos = strRespons.Find(szSession,0);
 char * temp=strstr(res+sta,dest);
 if(temp!=NULL)
  return temp-res-sta;
 else
  return -1;
}

//
// Construction/Destruction
//
CHttpSocket::CHttpSocket()
{
    m_s=NULL;
    m_phostent=NULL;
    m_port=80;
    m_bConnected=FALSE;
    for(int i=0;i<256;i++)
        m_ipaddr[i]='\0';
    memset(m_requestheader,0,MAXHEADERSIZE);
    memset(m_ResponseHeader,0,MAXHEADERSIZE);
    m_nCurIndex = 0;        //
    m_bResponsed = FALSE;
 m_nResponseHeaderSize = -1;
}

CHttpSocket::~CHttpSocket()
{
    CloseSocket();
}

BOOL CHttpSocket::Socket()
{
    if(m_bConnected)return FALSE;
 
    struct protoent *ppe;
    ppe=getprotobyname("http");
 WORD wVersion=MAKEWORD(1,1);
 WSADATA wsData;
 int nResult= WSAStartup(wVersion,&wsData); //1、启动Winsock
 if(nResult !=0)
 {
  printf("启动Winsock失败!\n");
 }
    ///创建SOCKET对象
    m_s=socket(PF_INET,SOCK_STREAM,IPPROTO_IP);
    if(m_s==INVALID_SOCKET)
    {
        //printf("socket()函数执行失败!\n");
        return FALSE;
    }
 
     return TRUE;
 
}

BOOL CHttpSocket::Connect(char *szHostName,int nPort)
{
    if(szHostName==NULL)
        return FALSE;
 
    ///若已经连接,则先关闭
    if(m_bConnected)
    {
        CloseSocket();
    }
 
    ///保存端口号
    m_port=nPort;
 
    ///根据主机名获得IP地址
    m_phostent=gethostbyname(szHostName);
    if(m_phostent==NULL)
    {
        printf("gethostbyname()函数执行失败!\n");
        return FALSE;
    }   
    ///连接
   struct sockaddr_in ip_addr;
   memcpy(&ip_addr.sin_addr.s_addr,m_phostent->h_addr_list[0],4);///h_addr_list[0]里4个字节,每个字节8位
   char str[40]={0};
   sprintf(str,"%s",inet_ntoa(ip_addr.sin_addr));
   struct sockaddr_in destaddr;
    memset((void *)&destaddr,0,sizeof(destaddr));
    destaddr.sin_family=AF_INET;
    destaddr.sin_port=htons(80);
    destaddr.sin_addr=ip_addr.sin_addr;
 
    ///保存主机的IP地址字符串
    sprintf(m_ipaddr,"%d.%d.%d.%d",
        destaddr.sin_addr.S_un.S_un_b.s_b1,
        destaddr.sin_addr.S_un.S_un_b.s_b2,
        destaddr.sin_addr.S_un.S_un_b.s_b3,
        destaddr.sin_addr.S_un.S_un_b.s_b4);
 
    if(connect(m_s,(struct sockaddr*)&destaddr,sizeof(destaddr))!=0)
    {
  //    printf(NULL,"connect()函数执行失败!","错误",MB_OK);
        return FALSE;
    }
    ///设置已经连接的标志
    m_bConnected=TRUE;
    return TRUE;
}

//根据请求的相对URL输出HTTP请求头
const char *CHttpSocket::FormatRequestHeader(char *pServer,char *pObject, long &Length,
            char *pCookie,char *pReferer,long nFrom,
            long nTo,int nServerType)
{
    char szPort[10];
    char szTemp[20];
    sprintf(szPort,"%d",m_port);
    memset(m_requestheader,'\0',1024);
 
    ///第1行:方法,请求的路径,版本
    strcat(m_requestheader,"GET ");
    strcat(m_requestheader,pObject);
    strcat(m_requestheader," HTTP/1.1");
    strcat(m_requestheader,"\r\n");
 
    ///第2行:主机
    strcat(m_requestheader,"Host:");
    strcat(m_requestheader,pServer);
    strcat(m_requestheader,"\r\n");
 
    ///第3行:
    if(pReferer != NULL)
    {
        strcat(m_requestheader,"Referer:");
        strcat(m_requestheader,pReferer);
        strcat(m_requestheader,"\r\n");       
    }
 
    ///第4行:接收的数据类型
    strcat(m_requestheader,"Accept:*/*");
    strcat(m_requestheader,"\r\n");
 
    ///第5行:浏览器类型
    strcat(m_requestheader,"User-Agent:Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)");
    strcat(m_requestheader,"\r\n");
 
    ///第6行:连接设置,保持
    strcat(m_requestheader,"Connection:Keep-Alive");
    strcat(m_requestheader,"\r\n");
 
    ///第7行:Cookie.
    if(pCookie != NULL)
    {
        strcat(m_requestheader,"Set Cookie:0");
        strcat(m_requestheader,pCookie);
        strcat(m_requestheader,"\r\n");
    }
 
    ///第8行:请求的数据起始字节位置(断点续传的关键)
    if(nFrom > 0)
    {
        strcat(m_requestheader,"Range: bytes=");
        _ltoa(nFrom,szTemp,10);
        strcat(m_requestheader,szTemp);
        strcat(m_requestheader,"-");
        if(nTo > nFrom)
        {
            _ltoa(nTo,szTemp,10);
            strcat(m_requestheader,szTemp);
        }
        strcat(m_requestheader,"\r\n");
    }
   
    ///最后一行:空行
    strcat(m_requestheader,"\r\n");
 
    ///返回结果
    Length=strlen(m_requestheader);
    return m_requestheader;
}

///发送请求头
BOOL CHttpSocket::SendRequest(const char *pRequestHeader, long Length)
{
    if(!m_bConnected)return FALSE;
 
    if(pRequestHeader==NULL)
        pRequestHeader=m_requestheader;
    if(Length==0)
        Length=strlen(m_requestheader);
 
    if(send(m_s,pRequestHeader,Length,0)==SOCKET_ERROR)
    {
        printf("send()函数执行失败!\n");
        return FALSE;
    }
    int nLength;
    GetResponseHeader(nLength);
    return TRUE;
}

long CHttpSocket::Receive(char* pBuffer,long nMaxLength)
{
    if(!m_bConnected)return NULL;
 
    ///接收数据
    long nLength;
    nLength=recv(m_s,pBuffer,nMaxLength,0);
   
    if(nLength <= 0)
    {
        //MessageBox(NULL,"recv()函数执行失败!","错误",MB_OK);
        CloseSocket();
    }
    return nLength;
}

///关闭套接字
BOOL CHttpSocket::CloseSocket()
{
    if(m_s != NULL)
    {
        if(closesocket(m_s)==SOCKET_ERROR)
        {
           // printf("closesocket()函数执行失败!\n");
            return FALSE;
        }
    }
    m_s = NULL;
    m_bConnected=FALSE;
    return TRUE;
}

int CHttpSocket::GetRequestHeader(char *pHeader, int nMaxLength) const
{
    int nLength;
    if(int(strlen(m_requestheader))>nMaxLength)
    {
        nLength=nMaxLength;
    }
    else
    {
        nLength=strlen(m_requestheader);
    }
    memcpy(pHeader,m_requestheader,nLength);
    return nLength;
}

//设置接收或者发送的最长时间
BOOL CHttpSocket::SetTimeout(int nTime, int nType)
{
    if(nType == 0)
    {
        nType = SO_RCVTIMEO;
    }
    else
    {
        nType = SO_SNDTIMEO;
    }
 
    DWORD dwErr;
    dwErr=setsockopt(m_s,SOL_SOCKET,nType,(char*)&nTime,sizeof(nTime));
    if(dwErr)
    {
        printf("setsockopt()函数执行失败!\n");
        return FALSE;
    }
    return TRUE;
}

//获取HTTP请求的返回头
const char* CHttpSocket::GetResponseHeader(int &nLength)
{
    if(!m_bResponsed)
    {
        char c = 0;
        int nIndex = 0;
        BOOL bEndResponse = FALSE;
        while(!bEndResponse && nIndex < MAXHEADERSIZE)
        {
            recv(m_s,&c,1,0);
            m_ResponseHeader[nIndex++] = c;
            if(nIndex >= 4)
            {
                if(m_ResponseHeader[nIndex - 4] == '\r' && m_ResponseHeader[nIndex - 3] == '\n'
                    && m_ResponseHeader[nIndex - 2] == '\r' && m_ResponseHeader[nIndex - 1] == '\n')
     bEndResponse = TRUE;
            }
        }
        m_nResponseHeaderSize = nIndex;
        m_bResponsed = TRUE;
    }
   
    nLength = m_nResponseHeaderSize;
    return m_ResponseHeader;
}

//返回HTTP响应头中的一行.
int CHttpSocket::GetResponseLine(char *pLine, int nMaxLength)
{
    if(m_nCurIndex >= m_nResponseHeaderSize)
    {
        m_nCurIndex = 0;
        return -1;
    }
 
    int nIndex = 0;
    char c = 0;
    do
    {
        c = m_ResponseHeader[m_nCurIndex++];
        pLine[nIndex++] = c;
    } while(c != '\n' && m_nCurIndex < m_nResponseHeaderSize && nIndex < nMaxLength);
   
    return nIndex;
}

int CHttpSocket::GetField(const char *szSession, char *szValue, int nMaxLength)
{
    //取得某个域值
    if(!m_bResponsed) return -1;
   
   // CString strRespons;
   // strRespons = m_ResponseHeader;
    int nPos = -1;
  //   nPos = strRespons.Find(szSession,0);
  nPos=FindPos(m_ResponseHeader,szSession);
//  if(temp!=NULL)
//  nPos=temp-m_ResponseHeader;
    if(nPos != -1)
    {
        nPos += strlen(szSession);
        nPos += 2;
        int nCr = FindPos(m_ResponseHeader,"\r\n",nPos);
        //CString strValue = strRespons.Mid(nPos,nCr - nPos);
        strcpy(szValue,m_ResponseHeader+nPos);
  *(szValue+nCr)=0;
        return nCr;//nCr - nPos
    }
     else
    {
        return -1;
    }
}


int CHttpSocket::GetServerState()
{
    //若没有取得响应头,返回失败
    if(!m_bResponsed) return -1;
   
    char szState[3];
    szState[0] = m_ResponseHeader[9];
    szState[1] = m_ResponseHeader[10];
    szState[2] = m_ResponseHeader[11];
 
    return atoi(szState);
}


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 跨平台socket封装是指为了在不同操作系统或者硬件平台上运行的应用程序之间进行网络通信,将socket API进行封装,提供统一的接口来使得应用程序可以方便地进行网络通信。由于在不同操作系统或者硬件平台上,socket API的实现方式有所不同,因此需要对不同平台进行适配和封装。跨平台socket封装的目的是方便开发人员进行网络通信,同时提高应用程序的可移植性、兼容性和可扩展性。在跨平台socket封装中,可以使用一些开源的第三方库,比如Boost.Asio、libevent等。这些第三方库提供了一些封装接口,使得应用程序能够使用统一的方式来进行网络编程。 在使用跨平台socket封装时,需要注意以下几点: 1.不同操作系统之间可能存在差异,需要进行相应的适配和兼容性测试。 2.在进行网络通信时,要保证通信协议的一致性,避免数据传输出现丢包或者粘包等问题。 3.要充分理解每个函数的含义和参数,以保证网络编程的正确性和可靠性。 总之,跨平台socket封装为应用程序提供了简单、方便、可移植的网络编程方式,是现代网络通信的重要组部分。 ### 回答2: 跨平台socket封装是一种将不同操作系统的socket细节进行封装的技术。通过跨平台socket封装,我们可以让不同操作系统的socket代码在不进行修改的情况下在不同的平台上运行。这样可以加快开发者的开发速度,同时降低代码维护难度。 跨平台socket封装技术的实现需要解决两个问题:一是不同操作系统对socket函数的实现细节不同,导致代码实现难度大,需要针对每个操作系统单独编写代码;二是跨平台socket封装技术需要充分考虑移植性问题,需要确保在不同操作系统和硬件平台上稳定运行。 为了解决这些问题,跨平台socket封装技术通常采用C或C++语言编写,使用平台无关的API,例如POSIX API或者Winsock API。同时,跨平台socket封装也需要具备跨平台的编译和构建环境,例如常用的Cmake或者Autotools。 跨平台socket封装的好处是显而易见的,它不仅可以提高开发者的效率,还可以降低代码维护的难度。但是需要注意的是,跨平台socket封装并不是万能的,它需要根据实际应用场景进行选择。如果仅仅是针对特定平台开发应用,使用原生的socket API可能更加简单有效。但是在开发跨平台应用或者框架时,使用跨平台socket封装技术是非常重要的。 ### 回答3: 跨平台socket封装是一种将底层的socket通信接口进行封装,使得在不同的操作系统以及开发语言中实现socket通信更加简单和便捷的工具。封装后的跨平台socket可以隐藏底层操作系统的差异性,以统一的接口供用户使用,提高了代码的可复用性和跨平台移植性。 跨平台socket封装可以通过使用库的方式进行实现,例如常见的Socket.io和Boost.asio库等。这些库提供了高层次的API,使得开发者不再需要关注不同平台和语言下socket通信的实现细节,而是可以直接调用封装好的API进行开发。同时,这些库也提供了众多的工具和函数,能够帮助开发者更加便捷的进行socket通信的开发和调试。 跨平台socket封装的优点不仅在于提高编程效率,还可以提高系统的灵活性和可扩展性。开发者可以更加方便地进行平台切换和升级,同时还可以通过简单的调用来实现多个设备之间的通信。 总之,跨平台socket封装的出现大大方便了软件开发工作,能够满足当今多样化、交互性强的移动互联网市场需求,为开发者提供了高效、可靠的网络通信解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值