阻塞套接字类-CPP文件

类别:编程语言 点击:0 评论:0 推荐:

// MySocket.cpp: implementation of the CMySocket class.
//
// ------------------------------------
// *   程 序 名:MySocket.h
// *   包    名:网络套接字封装类
// *   功    能:封装网络地址
// *   依赖组件:头文件MySocket.h中的两个类
// *   作    者:fusx
// *   开发日期:2003/06/11
// *   修改日期:2004/06/06
// *   项目名称:
// *   版    权:
// ------------------------------------
////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MySocket.h"
#include <crtdbg.h>
#include <assert.h>

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

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

CMySocket::CMySocket():m_hSocket(INVALID_SOCKET)
,m_nErrCode(0)
{
}

CMySocket::~CMySocket()
{
 assert(m_hSocket == INVALID_SOCKET);
 WSACleanup();
}

void CMySocket::operator =(SOCKET sck)
{
 assert(m_hSocket == INVALID_SOCKET);
 m_hSocket = sck;
}
//创建套接字
bool CMySocket::Create(int nType)
{
 assert(m_hSocket == INVALID_SOCKET);

 WSADATA wsaData;
 if (WSAStartup(MAKEWORD(2, 2), &wsaData))
 {
  m_nErrCode = WSAGetLastError();
  return false;
 }
 if((m_hSocket = socket(AF_INET, nType, 0)) == INVALID_SOCKET)
 {
  m_nErrCode = WSAGetLastError();
  return false;
 }
 return true;
}

//绑定套接字
bool CMySocket::Bind(LPCSOCKADDR psa)
{
 assert(m_hSocket != INVALID_SOCKET);

 if(bind(m_hSocket, psa, sizeof(SOCKADDR)) == SOCKET_ERROR)
 {
  m_nErrCode = WSAGetLastError();
  return false;
 }
 return true;
}
//侦听套接字
bool CMySocket::Listen()
{
 assert(m_hSocket != INVALID_SOCKET);

 if(listen(m_hSocket, 5) == SOCKET_ERROR)
 {
  m_nErrCode = WSAGetLastError();
  return false;
 }
 return true;
}

//连接服务器
bool CMySocket::Connect(LPCSOCKADDR psa)
{
 assert(m_hSocket != INVALID_SOCKET);

 // should timeout by itself
 if(connect(m_hSocket, psa, sizeof(SOCKADDR)) == SOCKET_ERROR)
 {
  m_nErrCode = WSAGetLastError();
  return false;
 }
 return true;
}

//接受套接字
bool CMySocket::Accept(CMySocket& sConnect, LPSOCKADDR psa,int nSecs)
{
 assert(m_hSocket != INVALID_SOCKET);
 assert(sConnect.m_hSocket == INVALID_SOCKET);
 
 //设置超时
 if (nSecs !=0)
 {
  FD_SET fd = {1, m_hSocket};
  TIMEVAL tv = {nSecs, 0};
  if (select(0, &fd, NULL, NULL, &tv) == 0)
  {
   m_nErrCode = WSAETIMEDOUT;
   return false;
  }
 }

 //接收连接套接字
 int nLengthAddr = sizeof(SOCKADDR);
 sConnect.m_hSocket = accept(m_hSocket, psa, &nLengthAddr);
 if(sConnect == INVALID_SOCKET)
 {
  m_nErrCode = WSAGetLastError();
  return false;  
 }
 return true;
}

//发送数据,返回值是发送出去的数据字节,不一定是全部数据
bool CMySocket::Send(const char* pch, const int nSize, int& nBytesSent,int nSecs)
{
 assert(m_hSocket != INVALID_SOCKET);

 //如果客户端取消了读数据,则返回值要小于nSize
 FD_SET fd = {1, m_hSocket};
 TIMEVAL tv = {nSecs, 0};
 if (select(0, NULL, &fd, NULL, &tv) == 0)
 {
  m_nErrCode = WSAETIMEDOUT;
  return false;
 } 
 //
 if((nBytesSent = send(m_hSocket, pch, nSize, 0)) == SOCKET_ERROR)
 {
  m_nErrCode = WSAGetLastError();
  return false;  
 }
 return true;
}

//发送全部指定的数据
bool CMySocket::Write(const char* pch, const int nSize, int nSecs)
{
 assert(m_hSocket != INVALID_SOCKET);

 //设置超时值
 FD_SET fd = {1, m_hSocket};
 TIMEVAL tv = {nSecs, 0};
 if ( select(0, NULL, &fd, NULL, &tv) == 0)
 {
  m_nErrCode = WSAETIMEDOUT;
  return false;
 }

 int nBytesSent = 0;
 int nBytesThisTime;
 const char* pch1 = pch;
 do
 {
  nBytesThisTime = send(m_hSocket, pch, nSize, 0);
  if ( nBytesThisTime == SOCKET_ERROR )
  {
   m_nErrCode = WSAGetLastError();
   return false;
  }
  nBytesSent += nBytesThisTime;
  pch1 += nBytesThisTime;
 } while(nBytesSent < nSize);
 return true;
}

//接受对方传来的数据,返回字节多少
//注意:如果套接字被关闭,则返回值为0字符
bool CMySocket::Receive(char* pch, const int nSize, int& nBytesReceived, int nSecs)
{
 assert(m_hSocket != INVALID_SOCKET);

 //设置超时
 FD_SET fd = {1, m_hSocket};
 TIMEVAL tv = {nSecs, 0};
 if ( select(0, &fd, NULL, NULL, &tv) == 0)
 {
  m_nErrCode = WSAETIMEDOUT;
  return false;
 }
 //
 nBytesReceived = recv(m_hSocket, pch, nSize, 0);
 if(nBytesReceived == SOCKET_ERROR)
 {
  m_nErrCode = WSAGetLastError();
  return false;
 }
 return true;
}
/*
bool CMySocket::Read(char* pch, const int nSize,int nBytesRead,int nSecs)
{
 assert( m_hSocket != INVALID_SOCKET);

 FD_SET fd = {1,m_hSocket};
 int nTimeout,nLeft=nBytesRead;
 char *pTemp = pch;
 do
 {
  if ( (nSecs==0) && (nMillSecs==0) )
   nTimeout = select(0, &fd, NULL, NULL, NULL);
  else
  {
   TIMEVAL tv = {nSecs,nMillSecs};
   nTimeout = select(0, &fd, NULL, NULL, &tv);
  }
  if (nTimeout == 0)
  {
   nErrCode = WSAGetLastError();
   return false;
  }
  //
  int nBytesReceived = recv(m_hSocket, pTemp, nLeft, 0);
  if(nBytesReceived == SOCKET_ERROR)
  {
   nErrCode = WSAGetLastError();
   return false;
  }
  pTemp += nBytesReceived;
  nLeft -= nBytesReceived;
 } while(nLeft<=0);
 return true;
}
*/
//接受数据报,返回接受到的数据字节
bool CMySocket::ReceiveDatagram( LPSOCKADDR psa,char* pch, const int nSize, int& nBytesReceived,int nSecs)
{
 assert(m_hSocket != INVALID_SOCKET);

 //设置超时
 FD_SET fd = {1, m_hSocket};
 TIMEVAL tv = {nSecs, 0};
 if ( select(0, NULL, &fd, NULL, &tv) == 0)
 {
  m_nErrCode = WSAETIMEDOUT;
  return false;
 }
 //接受的缓存空间应该大于全部的数据报
 int nFromSize = sizeof(SOCKADDR);
 nBytesReceived = recvfrom(m_hSocket,pch,nSize,0,psa,&nFromSize);
 if(nBytesReceived == SOCKET_ERROR)
 {
  m_nErrCode = WSAGetLastError();
  return false;
 }
 return true;
}

//发送数据报,返回发送出去的字节多少
bool CMySocket::SendDatagram(LPCSOCKADDR psa, const char* pch, const int nSize,  int& nBytesSent, int nSecs)
{
 assert(m_hSocket != INVALID_SOCKET);
 
 //设置超时
 FD_SET fd = {1, m_hSocket};
 TIMEVAL tv = {nSecs, 0};
 if ( select(0, NULL, &fd, NULL, &tv) == 0)
 {
  m_nErrCode = WSAETIMEDOUT;
  return false;
 }
 //
 nBytesSent = sendto(m_hSocket, pch, nSize, 0, psa, sizeof(SOCKADDR));
 if(nBytesSent == SOCKET_ERROR)
 {
  m_nErrCode = WSAGetLastError();
  return false;
 }
 return true;
}

//获取对方的套接字地址
bool CMySocket::GetPeerAddr(LPSOCKADDR psa)
{
 assert(m_hSocket != INVALID_SOCKET);
 //
 int nLengthAddr = sizeof(SOCKADDR);
 if(getpeername(m_hSocket, psa, &nLengthAddr) == SOCKET_ERROR)
  return false;

 return true;
}

//获取本地的套接字地址
bool CMySocket::GetSockAddr(LPSOCKADDR psa)
{
 assert(m_hSocket != INVALID_SOCKET);
 //
 int nLengthAddr = sizeof(SOCKADDR);
 if(getsockname(m_hSocket,psa,&nLengthAddr) == SOCKET_ERROR)
  return false;

 return true;
}

//static function
//根据名字获取主机地址
CSockAddr CMySocket::GetHostByName(const char* pchName,const USHORT ushPort/*=0*/)
{
 SOCKADDR_IN sockTemp;
 sockTemp.sin_family = AF_INET;
 sockTemp.sin_port = htons(ushPort);
 sockTemp.sin_addr.s_addr = 0;

 hostent* pHostEnt = gethostbyname(pchName);
 if(pHostEnt != NULL)
 {
  ULONG* pulAddr = (ULONG*) pHostEnt->h_addr_list[0];
  sockTemp.sin_addr.s_addr = *pulAddr; //地址已经是网络字节顺序
 }
 return sockTemp;
}

//static function
//根据地址获取主机名
const char* CMySocket::GetHostByAddr(LPCSOCKADDR psa)
{
 hostent* pHostEnt = gethostbyaddr((char*) &((LPSOCKADDR_IN) psa)
    ->sin_addr.s_addr, 4, PF_INET);
 if(pHostEnt == NULL)
 {
  return NULL;
 }
 return pHostEnt->h_name; // caller shouldn't delete this memory
}

//static function
//获取本地计算机的IP及主机名
bool CMySocket::GetLocalHostInfo(LPTSTR strHostName,LPTSTR strHostIP)
{
 // Get host name.
 char hostname[256];
 int res = gethostname(hostname,sizeof(hostname));
 if (res != 0)
  return false;

 strcpy(strHostName, hostname);

 // Get host info for hostname.
 hostent* pHostent = gethostbyname(hostname);
 if (pHostent==NULL)
  return false;

 // Parse the hostent information returned
 hostent &he = *pHostent;

 sockaddr_in sa;
 memcpy( &sa.sin_addr.s_addr, he.h_addr_list[0],he.h_length );

 //for (int nAdapter=0; he.h_addr_list[nAdapter]; nAdapter++)
 //{
 // memcpy ( &sa.sin_addr.s_addr, he.h_addr_list[nAdapter],he.h_length);
 //     // Output the machines IP Address.
 //    // TRACE("Address: %s\n", inet_ntoa(sa.sin_addr)); // display as string
 //}
 strcpy(strHostIP,inet_ntoa(sa.sin_addr));

 return true;
}


//关闭套接字
bool CMySocket::Close()
{//如果已经关闭了,则调用本函数也不会出错。
 if (INVALID_SOCKET == m_hSocket)
  return true;

 if(closesocket(m_hSocket) == SOCKET_ERROR)
 {
  m_nErrCode = WSAGetLastError();
  return false;
 }
 m_hSocket = INVALID_SOCKET;
 return true;
}

// 连接服务器
bool CMySocket::Connect(LPCTSTR strIP, int nPort)
{
 assert(m_hSocket != INVALID_SOCKET);
 
 // should timeout by itself
 CSockAddr  sa(strIP,nPort);
 if(connect(m_hSocket, sa, sizeof(SOCKADDR)) == SOCKET_ERROR)
 {
  m_nErrCode = WSAGetLastError();
  return false;
 }
 return true;
}

bool CMySocket::Bind(LPCTSTR strIP, int nPort)
{
 assert(m_hSocket != INVALID_SOCKET);

 CSockAddr sa(strIP,nPort);
 if(bind(m_hSocket, sa, sizeof(SOCKADDR)) == SOCKET_ERROR)
 {
  m_nErrCode = WSAGetLastError();
  return false;
 }
 return true;
}

//根据错误代码获取系统的出错字符串
bool CMySocket::GetErrorMessage(const int nErrCode, char *pErrMsg, int nMaxLen)
{
 assert(pErrMsg != NULL);
 
 LPVOID lpMsgBuf;
 DWORD dwLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_FROM_SYSTEM |
    FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL, nErrCode,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    (LPTSTR) &lpMsgBuf, 0, NULL );
 if (dwLen == 0)
 {
  pErrMsg[0] = 0;
  return false;
 }
 else
 {
  if ( nMaxLen > (int)dwLen )
   nMaxLen = (int)dwLen;
  memcpy(pErrMsg,lpMsgBuf,nMaxLen-1);
  pErrMsg[nMaxLen-2] = 0;
  LocalFree( lpMsgBuf );
 }
 return true;
}

 

本文地址:http://com.8s8s.com/it/it24242.htm