// 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; }

|