MFC实现与手机客户端通信的http服务器

通过socket实现http协议,主要是处理从客户端(浏览器)读取请求和格式化发送的信息。

主要的程序在CBlockSocket.cpp中:

// blocksock.cpp (CBlockSocketException, CBlockSocket, CHttpBlockSocket)
#include <stdafx.h>
#include "BlockSock.h"

// Class CBlockSocketException
IMPLEMENT_DYNAMIC(CBlockSocketException, CException)

CBlockSocketException::CBlockSocketException(char* pchMessage)
{
 m_strMessage = pchMessage;
 m_nError = WSAGetLastError();
}

BOOL CBlockSocketException::GetErrorMessage(LPTSTR lpstrError, UINT nMaxError,
  PUINT pnHelpContext /*= NULL*/)
{

 char text[200];
 if(m_nError == 0)
 {
  wsprintf(text, "%s 错误", (const char*) m_strMessage);
 }
 else
 {
  wsprintf(text, "%s   错误号:#%d", (const char*) m_strMessage, m_nError);
 }
 strncpy(lpstrError, text, nMaxError - 1);
 return TRUE;
}

// Class CBlockSocket
IMPLEMENT_DYNAMIC(CBlockSocket, CObject)

void CBlockSocket::Cleanup()
{
 if(m_hSocket == NULL) return;
 VERIFY(closesocket(m_hSocket) != SOCKET_ERROR);
 m_hSocket = NULL;
}

void CBlockSocket::Create(int nType/*  = SOCK_STREAM*/ )
{
 ASSERT(m_hSocket == NULL);
 if((m_hSocket = socket(AF_INET, nType, 0)) == INVALID_SOCKET)
 {
  throw new CBlockSocketException("创建套接字(Create)");
 }
}

void CBlockSocket::Bind(LPCSOCKADDR psa)
{
 ASSERT(m_hSocket != NULL);
 if(bind(m_hSocket, psa, sizeof(SOCKADDR)) == SOCKET_ERROR)
 {
  throw new CBlockSocketException("绑定地址(Bind)");
 }
}

void CBlockSocket::Listen()
{
 ASSERT(m_hSocket != NULL);
 if(listen(m_hSocket, 5) == SOCKET_ERROR)
 {
  throw new CBlockSocketException("侦听连接(Listen)");
 }
}

BOOL CBlockSocket::Accept(CBlockSocket& sConnect, LPSOCKADDR psa)
{
 ASSERT(m_hSocket != NULL);
 ASSERT(sConnect.m_hSocket == NULL);
 int nLengthAddr = sizeof(SOCKADDR);
 sConnect.m_hSocket = accept(m_hSocket, psa, &nLengthAddr);
 if(sConnect == INVALID_SOCKET)
 {
  if(WSAGetLastError() != WSAEINTR)
  {
   throw new CBlockSocketException("接受连接(Accept)");
  }
  return FALSE;
 }
 return TRUE;
}

void CBlockSocket::Close()
{
 ASSERT(m_hSocket != NULL);
 if(closesocket(m_hSocket) == SOCKET_ERROR)
 {
  throw new CBlockSocketException("关闭套接字(Close)");
 }
 m_hSocket = NULL;
}

void CBlockSocket::Connect(LPCSOCKADDR psa)
{
 ASSERT(m_hSocket != NULL);
 if(connect(m_hSocket, psa, sizeof(SOCKADDR)) == SOCKET_ERROR)
 {
  throw new CBlockSocketException("发送连接(Connect)");
 }
}

int CBlockSocket::Write(const char* pch, const int nSize, const int nSecs)
{
 int nBytesSent = 0;
 int nBytesThisTime;
 const char* pch1 = pch;
 do
 {
  nBytesThisTime = Send(pch1, nSize - nBytesSent, nSecs);
  nBytesSent += nBytesThisTime;
  pch1 += nBytesThisTime;
 } while(nBytesSent < nSize);
 return nBytesSent;
}

int CBlockSocket::Send(const char* pch, const int nSize, const int nSecs)
{
 ASSERT(m_hSocket != NULL);
 FD_SET fd = {1, m_hSocket};
 TIMEVAL tv = {nSecs, 0};
 if(select(0, NULL, &fd, NULL, &tv) == 0)
 {
  throw new CBlockSocketException("发送超时(Send timeout)");
 }
 int nBytesSent;
 if((nBytesSent = send(m_hSocket, pch, nSize, 0)) == SOCKET_ERROR)
 {
  throw new CBlockSocketException("发送数据(Send)");
 }
 return nBytesSent;
}

int CBlockSocket::Receive(char* pch, const int nSize, const int nSecs)
{
 ASSERT(m_hSocket != NULL);
 FD_SET fd = {1, m_hSocket};
 TIMEVAL tv = {nSecs, 0};
 if(select(0, &fd, NULL, NULL, &tv) == 0)
 {
  throw new CBlockSocketException("接收超时(Receive timeout)");
 }

 int nBytesReceived;
 if((nBytesReceived = recv(m_hSocket, pch, nSize, 0)) == SOCKET_ERROR)
 {
  throw new CBlockSocketException("接收数据(Receive)");
 }
 return nBytesReceived;
}

int CBlockSocket::ReceiveDatagram(char* pch, const int nSize, LPSOCKADDR psa, const int nSecs)
{
 ASSERT(m_hSocket != NULL);
 FD_SET fd = {1, m_hSocket};
 TIMEVAL tv = {nSecs, 0};
 if(select(0, &fd, NULL, NULL, &tv) == 0)
 {
  throw new CBlockSocketException("接收超时(Receive timeout)");
 }

 int nFromSize = sizeof(SOCKADDR);
 int nBytesReceived = recvfrom(m_hSocket, pch, nSize, 0, psa, &nFromSize);
 if(nBytesReceived == SOCKET_ERROR)
 {
  throw new CBlockSocketException("接收数据报(ReceiveDatagram)");
 }
 return nBytesReceived;
}

int CBlockSocket::SendDatagram(const char* pch, const int nSize, LPCSOCKADDR psa, const int nSecs)
{
 ASSERT(m_hSocket != NULL);
 FD_SET fd = {1, m_hSocket};
 TIMEVAL tv = {nSecs, 0};
 if(select(0, NULL, &fd, NULL, &tv) == 0)
 {
  throw new CBlockSocketException("发送超时(Send timeout)");
 }

 int nBytesSent = sendto(m_hSocket, pch, nSize, 0, psa, sizeof(SOCKADDR));
 if(nBytesSent == SOCKET_ERROR)
 {
  throw new CBlockSocketException("发送数据报(SendDatagram)");
 }
 return nBytesSent;
}

void CBlockSocket::GetPeerAddr(LPSOCKADDR psa)
{
 ASSERT(m_hSocket != NULL);
 int nLengthAddr = sizeof(SOCKADDR);
 if(getpeername(m_hSocket, psa, &nLengthAddr) == SOCKET_ERROR)
 {
  throw new CBlockSocketException("获得对方地址(GetPeerName)");
 }
}

void CBlockSocket::GetSockAddr(LPSOCKADDR psa)
{
 ASSERT(m_hSocket != NULL);
 int nLengthAddr = sizeof(SOCKADDR);
 if(getsockname(m_hSocket, psa, &nLengthAddr) == SOCKET_ERROR)
 {
  throw new CBlockSocketException("获得本方地址(GetSockName)");
 }
}

CSocketAddress CBlockSocket::GetHostByName(const char* pchName, const USHORT ushPort /* = 0 */)
{
 hostent* pHostEnt = gethostbyname(pchName);
 if(pHostEnt == NULL)
 {
  throw new CBlockSocketException("通过名字查找主机(GetHostByName)");
 }
 ULONG* pulAddr = (ULONG*) pHostEnt->h_addr_list[0];
 SOCKADDR_IN sockTemp;
 sockTemp.sin_family = AF_INET;
 sockTemp.sin_port = htons(ushPort);
 sockTemp.sin_addr.s_addr = *pulAddr;
 return sockTemp;
}

const char* CBlockSocket::GetHostByAddr(LPCSOCKADDR psa)
{
 hostent* pHostEnt = gethostbyaddr((char*) &((LPSOCKADDR_IN) psa)
    ->sin_addr.s_addr, 4, PF_INET);
 if(pHostEnt == NULL)
 {
  throw new CBlockSocketException("通过地址查找主机(GetHostByAddr)");
 }
 return pHostEnt->h_name;
}

// Class CHttpBlockSocket
IMPLEMENT_DYNAMIC(CHttpBlockSocket, CBlockSocket)

CHttpBlockSocket::CHttpBlockSocket()
{
 m_pReadBuf = new char[nSizeRecv];
 m_nReadBuf = 0;
}

CHttpBlockSocket::~CHttpBlockSocket()
{
 delete [] m_pReadBuf;
}

//读取整个头信息,并在结尾加上字符串的结束标志
int CHttpBlockSocket::ReadHttpHeaderLine(char* pch, const int nSize, const int nSecs)
{
 int nBytesThisTime = m_nReadBuf;
 int nLineLength = 0;
 char* pch1 = m_pReadBuf;
 char* pch2;
 do
 {
  if((pch2 = (char*) memchr(pch1 , '/n', nBytesThisTime)) != NULL)
  {
   ASSERT((pch2) > m_pReadBuf);
   ASSERT(*(pch2 - 1) == '/r');
   nLineLength = (pch2 - m_pReadBuf) + 1;
   if(nLineLength >= nSize) nLineLength = nSize - 1;
   memcpy(pch, m_pReadBuf, nLineLength);
   m_nReadBuf -= nLineLength;
   memmove(m_pReadBuf, pch2 + 1, m_nReadBuf);
   break;
  }
  pch1 += nBytesThisTime;
  nBytesThisTime = Receive(m_pReadBuf + m_nReadBuf, nSizeRecv - m_nReadBuf, nSecs);
  if(nBytesThisTime <= 0)
  {
   throw new CBlockSocketException("获取头部信息(ReadHeaderLine)");
  }
  m_nReadBuf += nBytesThisTime;
 }
 while(TRUE);
 *(pch + nLineLength) = '/0';
 return nLineLength;
}

//读取传输的信息的其它部分(假定头信息已经读取了)
int CHttpBlockSocket::ReadHttpResponse(char* pch, const int nSize, const int nSecs)
{
 int nBytesToRead, nBytesThisTime, nBytesRead = 0;
 if(m_nReadBuf > 0)
 {
  memcpy(pch, m_pReadBuf, m_nReadBuf);
  pch += m_nReadBuf;
  nBytesRead = m_nReadBuf;
  m_nReadBuf = 0;
 }
 do
 {
  nBytesToRead = min(nSizeRecv, nSize - nBytesRead);
  nBytesThisTime = Receive(pch, nBytesToRead, nSecs);
  if(nBytesThisTime <= 0) break;
  pch += nBytesThisTime;
  nBytesRead += nBytesThisTime;
 }
 while(nBytesRead <= nSize);
 return nBytesRead;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值