⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netstream.cpp

📁 这是一个简单的使用WinAPI基于WinSock的ICP/IP程序
💻 CPP
字号:
// NetStream.cpp: implementation of the CNetStream class.
//
// Written by Marat Bedretdinov (maratb@hotmail.com)
// Copyright (c) 2000.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name is included. 
//
// If the source code in  this file is used in any commercial application 
// then acknowledgement must be made to the author of this file 
// and permissions to use this file are requested from the author
//
// (in whatever form you wish).// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage whatsoever.
// It's free - so you get what you pay for.//

#include "stdafx.h"

#include "NetConnection.h"
#include "NetFileConnector.h"
#include "NetMessage.h"
#include "NetStream.h"

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


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CNetStream::CNetStream() :
m_pConnector(0),
m_pFactory(0)
{
  m_pFactory = g_getDefaultMsgFactory();
}

CNetStream::~CNetStream()
{
// if there is a connection, close it and release the object
  _DELETE(m_pConnector)
}

//////////////////////////////////////////////////////////////////////
// this method lets the stream to redirect its data flow through a 
// differnet connector the return value is the previously used connector 

CNetConnection* CNetStream::Attach(CNetConnection* pConnector)
{
  CNetConnection* pPrevConnector = m_pConnector;
// assign new connection to the stream
  m_pConnector = pConnector;
  return pPrevConnector;
}

//////////////////////////////////////////////////////////////////////
// this method lets the stream to handle different type of messages
// the return value is the previsouly used message factory 
// there is no Deatch(CMsgFactory*) method, based on assumtion
// that factories are created statically

CMsgFactory* CNetStream::Attach(CMsgFactory* pFactory)
{
  CMsgFactory* pPrevFactory = m_pFactory;
// assign new msg factory to the stream
  m_pFactory = pFactory;
  return pPrevFactory;
}

//////////////////////////////////////////////////////////////////////
// this method makes the stream unusable, however the connector is
// preserved and may be reassociated with a different stream

CNetConnection* CNetStream::Detach()
{
  CNetConnection* pPrevConnector = m_pConnector;
  m_pConnector = 0;
  return pPrevConnector;
}

// returns true if underlaying protocol is connected
bool CNetStream::IsOpen() const
{
  return m_pConnector && m_pConnector->IsConnected();
}

bool CNetStream::IsThereData()
{
  return IsOpen() && m_pConnector->CanRead();
}

// reads data from the CNetConnector and constructs a CNetMsg out of it
CNetStream& CNetStream::operator>>(CNetMsg*& pMsg)
{
  pMsg = 0;
// if not connected - exception
  if (!m_pConnector || !m_pConnector->IsConnected()) 
    throw CNetException(ERR_NET_NOT_CONNECTED, "bool CNetStream::Read()");

  try {
// wait until there is data. Note that if connection is broken CanRead() throws an exception
   while (!m_pConnector->CanRead())
     Sleep(0);
// read the message from the stream
   CNetMsg::Read(this, pMsg);
  } catch (CNetException e) {
	_DELETE(pMsg);
	pMsg = 0;
	throw e;
  }
  return *this;
}

// write data from CNetMsg into the CNetConnector
CNetStream& CNetStream::operator<<(CNetMsg& msg)
{
// if not connected - exception
  if (!m_pConnector || !m_pConnector->IsConnected()) 
	throw CNetException(ERR_NET_NOT_CONNECTED, "bool CNetStream::Read()");
// wait until I can write in. Note that if connection is broken CanWrite() throws an exception
  try {
    while (!m_pConnector->CanWrite())
      Sleep(0);
// write the member variables (header + message body) into void* and send it
    msg.Write(this);
  } catch (CNetException e) {
	throw e;
  }
  return *this;
}

// this sends only with a single message at a time and only its "simple" data
// a CNetMsg derivable takes care of its children
void CNetStream::Write(CNetMsg& msg)
{
// get the message header
  CNetMsgHdr* pHdr = msg.GetMsgHdr();
// write the message header data into the socket stream
  m_pConnector->Write(pHdr->GetData(), pHdr->GetSize_Write());
// now write the message body data into the socket stream
  m_pConnector->Write(msg.GetData(), msg.GetSize_Write());
// the void* buffer is not needed any longer
  pHdr->EmptyBuffer();
  msg.EmptyBuffer();
}

CNetMsg* CNetStream::CreateMessage(long nClassId)
{
  if (!m_pFactory)  
    throw CNetMsgException(ERR_NET_NO_MSG_FACTORY, "CNetMsg* CNetStream::CreateMessage()");

  return m_pFactory->CreateMessage(nClassId);
}

/*
// read the header data. CNetMsgHdr::m_pData now points to the data
   m_pConnector->Read(pHeader->AllocateData(), pHeader->GetSize_Read());
// parse out the member variables from m_pData
   pHeader->Read();
// create the message class based on the message class name
   //pMsg = dynamic_cast<CNetMsg*>(CREATE(g_MessageClassNames[pHeader->GetMSG().m_nClassId].m_strClassName));
   pMsg = CreateMessage(pHeader->GetMSG().m_nClassId);
   if (!pMsg) 
     throw CNetMsgException(ERR_NET_MSG_UKNOWN_TYPE, "CNetStream& CNetStream::operator>>(CNetMsg*&)");
// now read the message body data. CNetMsg[derived]::m_pData now points to the data
   m_pConnector->Read(pMsg->AllocateData(pHeader->GetMsgSize()), pHeader->GetMsgSize());
// release header.m_pData, because if I don't, then the CNetMsgHdr::operator=()
// will allocate a new m_pData for pMsg->m_header::m_pData and copy 
// the context. That would be an overkill. I don't need this info anymore, 
// since the member variables are properly populated already
   pHeader->EmptyBuffer();
// copy header's member variables
   pMsg->GetMsgHdr()->operator=(*pHeader);
// parse out the member variables from m_pData
   pMsg->ReadBody();
   if (pMsg->HasChildren())
	 pMsg->ReadChildren(this);
// release the message's m_Data
   pMsg->EmptyBuffer();
   delete pHeader;
*/

// reads data from the CNetConnector and constructs a CNetMsg out of it
CNetStream& CFlatStream::operator>>(CNetMsg*& pMsg)
{
  pMsg = 0;
  char* pBuff = 0;
// if not connected - exception
  if (!m_pConnector || !m_pConnector->IsConnected()) 
    throw CNetException(ERR_NET_NOT_CONNECTED, "bool CNetStream::Read()");

  try {
   CNetFileConnector* pConnector = dynamic_cast<CNetFileConnector*>(m_pConnector);
   if (!pConnector)
	 throw CNetMsgException(ERR_NET_BAD_CONNECTION_HANDLER, "CNetStream& CPacketStream::operator>>(CNetMsg*& pMsg)");
// wait until there is data. Note that if connection is broken CanRead() throws an exception
   while (!m_pConnector->CanRead())
     Sleep(0);
// find out how much I can read.
// request as mach as I can, return will have the max possible value
   ulong nLen = pConnector->CanRead(CNetPacket::GetMaxSize_Packet());
// read the message from the stream
   pMsg = new CNetPacket;
   pBuff = new char[nLen];
   pConnector->Read(pBuff, nLen);

// figure out the sequence number of this packet
   ulong nSeqN = (pConnector->GetCurrentPos() + CNetPacket::GetMaxSize_Packet() - 1) / CNetPacket::GetMaxSize_Packet();
   ((CNetPacket*)pMsg)->SetData(pBuff, nLen, nSeqN);

  } catch (CNetException e) {
	_DELETE(pMsg);
	_DELETE(pBuff);
	throw e;
  }
  delete pBuff;
  return *this;
}

// write data from CNetMsg into the CNetConnector
CNetStream& CFlatStream::operator<<(CNetMsg& msg)
{
// if not connected - exception
  if (!m_pConnector || !m_pConnector->IsConnected()) 
	throw CNetException(ERR_NET_NOT_CONNECTED, "bool CNetStream::Read()");
// wait until I can write in. Note that if connection is broken CanWrite() throws an exception
  try {
   CNetFileConnector* pConnector = dynamic_cast<CNetFileConnector*>(m_pConnector);
   while (!pConnector->CanWrite())
      Sleep(0);

// just write the body of the packet
    CNetPacket& packet = dynamic_cast<CNetPacket&>(msg);
	pConnector->Write(packet.GetData(), packet.GetSize());

  } catch (bad_cast e) {
	throw CNetMsgException(ERR_NET_MSG_UKNOWN_TYPE, "CNetStream& CPacketStream::operator<<(CNetMsg& msg)");
  } catch (CNetException e) {
	throw e;
  }
  return *this;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -