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

📄 netsockconnection.cpp

📁 这是一个简单的使用WinAPI基于WinSock的ICP/IP程序
💻 CPP
字号:
// NetSockConnection.cpp: implementation of the CNetSockConnection 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 "NetIPAddress.h"
#include "NetSockConnection.h"

#ifdef _WIN32
  #ifdef _DEBUG
  #undef THIS_FILE
  static char THIS_FILE[]=__FILE__;
  #define new DEBUG_NEW
  #endif
#endif 
 
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#ifdef _WIN32
  bool CNetSockConnection::m_bWinSockLoaded = false;
#else
#endif

#define PR_TCP 6 // TCP protocol number for 'socket' call

CNetSockConnection::CNetSockConnection():
m_hSocket(0)
{
#ifdef _WIN32
  InitWinSock();
#endif
// create the socket
  m_hSocket = socket(AF_INET, SOCK_STREAM, PR_TCP);
  if (m_hSocket == INVALID_SOCKET) {
    Disconnect();
    HandleException(ERR_NET_FAILED_CREATE_SOCKET, "CNetSockConnection::CNetSockConnection()");
  }
}

CNetSockConnection::CNetSockConnection(SOCKET hSocket):
m_hSocket(hSocket)
{
}

CNetSockConnection::~CNetSockConnection()
{
  Disconnect();
}

void CNetSockConnection::Disconnect()
{
// graceful shutdown
#ifdef _WIN32
//  shutdown(m_hSocket, SD_BOTH);
  int n = closesocket(m_hSocket);
#else
  close((int)m_hSocket);
#endif
}

void CNetSockConnection::Read(void* pBuff, unsigned long nSize)
{
  if (!IsConnected()) 
      HandleException(ERR_NET_NOT_CONNECTED, "void CNetSockConnection::Read(void*, unsigned long)");

// receive the buffer of the size nSize
// the size of the last received packet
  m_nLastPacketSz = 0;
// the total size of receieved data
  int nTotalRead = 0;
// while there is still data to read
  while (nSize > 0) {
// read as much as was received (up to nSize)
    m_nLastPacketSz = recv(m_hSocket, (char*)pBuff + nTotalRead, nSize, 0);
    if (m_nLastPacketSz == SOCKET_ERROR || m_nLastPacketSz <= 0) 
      HandleException(ERR_NET_FAILED_READ, "void CNetSockConnection::Read(void*, unsigned long)");

// let the subcriber know than m_nLastPacketSz bytes have been received
    InvokeCallBack();
// increment nTotalRead by m_nLastPacketSz
	nTotalRead += m_nLastPacketSz;
// decrement nSize by m_nLastPacketSz
    nSize -= m_nLastPacketSz;
  }
}

void CNetSockConnection::Write(const void* pBuff, unsigned long nSize)
{
  if (!IsConnected()) 
     HandleException(ERR_NET_NOT_CONNECTED, "void CNetSockConnection::Write(void*, unsigned long)");

// send the buffer in packets, each is maximum nSize long
// the size of the last sent packet
  m_nLastPacketSz = 0;
// the total bytes sent
  int nTotalSent = 0;
// while still have data to sent
  while (nSize > 0) {
// send as much as TCP layer can take
    m_nLastPacketSz = send(m_hSocket, (const char*)pBuff + nTotalSent, nSize, 0);
    if (m_nLastPacketSz == SOCKET_ERROR || m_nLastPacketSz <= 0) 
      HandleException(ERR_NET_FAILED_SEND, "void CNetSockConnection::Write(void*, unsigned long)");
// let the subcriber know than m_nLastPacketSz bytes have been sent
    InvokeCallBack();
// increment nTotalSent by m_nLastPacketSz
	nTotalSent += m_nLastPacketSz;
// decrement nSize by m_nLastPacketSz
    nSize -= m_nLastPacketSz;
  }
}

// changes the socket from/to blocking/nonblocking
void CNetSockConnection::SetBlocking(bool bOn)
{
  if (!IsConnected()) 
    HandleException(ERR_NET_NOT_CONNECTED, "void CNetSockConnection::Write(void*, unsigned long)");

  ulong opt = (ulong)!bOn;
  int nCode = ioctlsocket(m_hSocket, FIONBIO, &opt);

  if (nCode == SOCKET_ERROR) 
    HandleException(ERR_NET_FAILED_SOCKOPT, "void CNetSockConnection::SetBlocking(bool)");
}

bool CNetSockConnection::CanRead()
{
  if (!IsConnected()) return false;

  fd_set readHandles;
  struct timeval CallTimeout;
// Setup timeout for 'select' call

  CallTimeout.tv_sec = m_nTimeout/1000;
  CallTimeout.tv_usec = m_nTimeout % 1000;

// Setup array for 'select' call
  FD_ZERO(&readHandles);
  FD_SET(m_hSocket, &readHandles);
// Test which Handles is Ready for Read via 'select' call
  int nFds = select(m_hSocket + 1, &readHandles, 0, 0, &CallTimeout);
  if (nFds == SOCKET_ERROR || nFds < 0)
    HandleException(ERR_NET_FAILED_SELECT, "void CNetSockConnection::CanRead()");
// timed out
  if (nFds == 0)
    return false;
// Test 'm_hSocket' (ready or not) & return result
  return FD_ISSET(m_hSocket, &readHandles) != 0;
}

bool CNetSockConnection::CanWrite()
{
  if (!IsConnected()) return false;

  fd_set writeHandles;
  struct timeval  CallTimeout;
 
// Setup timeout for 'select' call as 50 ms - by default
  CallTimeout.tv_sec = m_nTimeout/1000;
  CallTimeout.tv_usec = m_nTimeout % 1000;
// Setup array for 'select' call
  FD_ZERO(&writeHandles);
  FD_SET(m_hSocket, &writeHandles);
// Test which Handles is Ready for Write via 'select' call
  int nFds = select(m_hSocket + 1, 0, &writeHandles, 0, &CallTimeout);
  if (nFds == SOCKET_ERROR || nFds < 0)
    HandleException(ERR_NET_FAILED_SELECT, "void CNetSockConnection::CanWrite()");
  if (nFds == 0)
    return false;
// Test 'm_ioHandle' (ready or not) & return result
  return FD_ISSET(m_hSocket, &writeHandles) != 0;
}

bool CNetSockConnection::IsConnected() const
{
  return m_hSocket > 0;
}

void CNetSockConnection::GetRemoteAddr(CNetAddress& obj) const
{
  if (!IsConnected())
    HandleException(ERR_NET_NOT_CONNECTED, "void CNetSockConnection::GetRemoteAddr(CNetAddress& addr)");

  CNetIPAddress& addr = dynamic_cast<CNetIPAddress&>(obj);

  struct sockaddr SocketAddr;
  int SocketAddrSize = sizeof(SocketAddr);
// get remote socket address as 'struct sockaddr'
  if (getpeername(m_hSocket, &SocketAddr, &SocketAddrSize) == SOCKET_ERROR)
    HandleException(ERR_NET_CANNOT_RESOLVE_PEER_ADDRESS, "void CNetSockConnection::GetRemoteAddr(CNetAddress& addr)");
// if OK -> convert 'struct sockaddr' to a connect string format
  addr.SetConnectString(&SocketAddr);
}

void CNetSockConnection::GetLocalAddr(CNetAddress& obj) const
{
  if (!IsConnected())
    HandleException(ERR_NET_NOT_CONNECTED, "void CNetSockConnection::GetRemoteAddr(CNetAddress& addr)");

  CNetIPAddress& addr = dynamic_cast<CNetIPAddress&>(obj);

  struct sockaddr SocketAddr;
  int nSz = sizeof(SocketAddr);
// get local socket address as 'struct sockaddr'
  if (getsockname(m_hSocket, (sockaddr*)&SocketAddr, (int*)&nSz) == SOCKET_ERROR)
    HandleException(ERR_NET_CANNOT_RESOLVE_LOCAL_ADDRESS, "void CNetSockConnection::GetLocalAddr(CNetAddress& addr)");
// if OK -> convert 'struct sockaddr' to a connect string format

  addr.SetConnectString(&SocketAddr);
}

ulong CNetSockConnection::GetRemoteHandle() const
{
  CNetIPAddress addr;
  GetRemoteAddr(addr);
  return g_addr_stu(addr.GetHostName());
}

ulong CNetSockConnection::GetLocalHandle() const
{
  CNetIPAddress addr;
  GetLocalAddr(addr);
  return g_addr_stu(addr.GetHostName());
}

void CNetSockConnection::HandleException(int nNetErr, const char* strSrc) const
{
  throw CNetSockException(nNetErr, GetLastSocketError(), strSrc);
}

#ifdef _WIN32
void CNetSockConnection::InitWinSock()
{
  if (m_bWinSockLoaded) return;

  WORD wVerReq;
  WSADATA wsaData;
  int nErr; 
// try to get version 2 of WinSock interface
  wVerReq = MAKEWORD(2, 0); 
  nErr = WSAStartup(wVerReq, &wsaData );
  // could not find a usable WinSock DLL.                                  
  if (nErr) 
        throw CNetSockException(ERR_NET_FAILED_INIT_DLL, GetLastSocketError(), "bool CNetSockConnection::InitWinSock() const");
  if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) {
    WSACleanup();
        throw CNetSockException(ERR_NET_FAILED_INIT_DLL, GetLastSocketError(), "bool CNetSockConnection::InitWinSock() const");
  }
  m_bWinSockLoaded = true;
}
#endif

⌨️ 快捷键说明

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