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

📄 socket.cpp

📁 经常用到的 socketAPI
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************
                          socket.cpp  -  description
                             -------------------
    begin                : Fri Jul 20 2001
    copyright            : (C) 2001 by Mark
    email                : alben@yeah.net
	modifier             : yt yfrom_to@sina.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#include <cstring>
#include <cstdio>
#include <iostream>

#include "mylibconf.h"
#include "socket.h"

using namespace std;
//#include <AFX.H>
namespace mylib
{

//存储本地ip,端口号
void CSocket::StoreLocalIP_PORT()	
{
	CInetAddress localInet; 
	#if defined(WIN32) 
	int nLen=sizeof(sockaddr); 
	#else  
	socklen_t nLen=sizeof(CInetAddress); 
	#endif 
	getsockname(m_iSocket,(sockaddr*)&localInet.m_stInetAddr,&nLen); 
	m_InetAddr=localInet; 
}
			


#if defined(WIN32)
Cinit_WSA::Cinit_WSA()
{
	WSADATA	wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData))
	{
		abort();
	}
}
Cinit_WSA::~Cinit_WSA()
{	WSACleanup(); }
#endif


CInetAddress::CInetAddress()
{
	memset(&m_stInetAddr, 0, sizeof(m_stInetAddr));
}



CInetAddress::CInetAddress(const struct sockaddr_in& stInetAddr)
{
	m_stInetAddr = stInetAddr;
}


//CInetAddress::CInetAddress(const char* sInetAddr)
//{
//	memset(&m_stInetAddr, 0, sizeof(m_stInetAddr));
//	*this=sInetAddr;
//}

CInetAddress::CInetAddress(const char* ipAddr,int  port)
{

	memset(&m_stInetAddr, 0, sizeof(m_stInetAddr));
	m_stInetAddr.sin_family = AF_INET;
	m_stInetAddr.sin_port = htons(port);
	if (strcmp(ipAddr, "*") == 0)
	{
		m_stInetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
		return;
	}

	if( (m_stInetAddr.sin_addr.s_addr=inet_addr(ipAddr)) == INADDR_NONE)
	{//  Internet host information structure
	    struct hostent  *lpHostEnt;
		#if defined(WIN32)	
		if (!(lpHostEnt = gethostbyname(ipAddr)))
		{
		throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
		}
		#else
		if (!(lpHostEnt = gethostbyname(ipAddr)))
		{
		throw CSocketException(strerror(errno), __FILE__, __LINE__);		
		}
		#endif
		
		m_stInetAddr= *((struct sockaddr_in *)lpHostEnt->h_addr_list[0]);
	}
}

bool CInetAddress::IsInetAddress() const
{
	struct sockaddr_in stInetAddr;
	memset(&stInetAddr, 0, sizeof(stInetAddr));
	if(memcmp(&m_stInetAddr, &stInetAddr, sizeof(m_stInetAddr)))
		return true;
	return false;
}

std::string  CInetAddress::GetIPaddstr(const char splitch) const
{
	if(m_stInetAddr.sin_addr.s_addr==INADDR_ANY)
		return string("");
	
    char strCmd[128];
#if defined(MYLIB_BIG_ENDIAN)
	sprintf(strCmd, "%d%c%d%c%d%c%d",
		(m_stInetAddr.sin_addr.s_addr>>24) & 0x000000ff,
        		splitch,
		(m_stInetAddr.sin_addr.s_addr>>16) & 0x000000ff,
		splitch,
		(m_stInetAddr.sin_addr.s_addr>>8) & 0x000000ff,
		splitch,
		(m_stInetAddr.sin_addr.s_addr) & 0x000000ff
		);
#elif defined(MYLIB_LITTLE_ENDIAN)
	sprintf(strCmd, "%d%c%d%c%d%c%d",
		(m_stInetAddr.sin_addr.s_addr) & 0x000000ff,
		        splitch,
		(m_stInetAddr.sin_addr.s_addr>>8) & 0x000000ff,
		        splitch,
		(m_stInetAddr.sin_addr.s_addr>>16) & 0x000000ff,
		        splitch,
		(m_stInetAddr.sin_addr.s_addr>>24) & 0x000000ff
		);
#endif	
	return string(strCmd);
}


CInetAddress& CInetAddress::operator = (const CInetAddress& sInetAddr)
{
   m_stInetAddr=sInetAddr.m_stInetAddr;
   return *this;
}

CInetAddress& CInetAddress::operator = (const struct sockaddr_in& stInetAddr)
{
	m_stInetAddr = stInetAddr;
	return *this;
}

/////////////////////////////////////////////////////////////////////////
// 函数名:operator = 
// 作  用:初始化,赋值内部数据。
// 参  数:"IP地址,端口号" 或者 "主机名:端口号"
// 返回值:CInetAddress&
// 修  改:
/////////////////////////////////////////////////////////////////////////
//CInetAddress& CInetAddress::operator = (const char* sInetAddr)
//{    
//
//    char *strport=strchr(sInetAddr,':');
//	if(strport==0)
//         return *this;
//    ++strport;//skip the ':'
//
//	char stripaddr[20];
//	char *pp=stripaddr;
//	for(const char *p=sInetAddr;p!=strport;p++)
//		*pp++=*p;
//    *pp='\0';
//
//	if (strcmp(stripaddr, "*") == 0)
//	{
//		m_stInetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
//		return *this;
//	}
//
//	m_stInetAddr.sin_family = AF_INET;
//	m_stInetAddr.sin_port = htons(atol(strport));
//	
//
//	//////////////////////////////////////////////////////////////////////////
//	//没有使用gethostbyname_r
//	//////////////////////////////////////////////////////////////////////////
//	
//	if( (m_stInetAddr.sin_addr.s_addr=inet_addr(stripaddr)) == INADDR_NONE)
//	{//  Internet host information structure
//	    struct hostent  *lpHostEnt;
//		if (!(lpHostEnt = gethostbyname(stripaddr)))
//		{
//        #if defined(WIN32)	
//		throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
//        #else
//		throw CSocketException(strerror(errno), __FILE__, __LINE__);
//        #endif
//		}
//		m_stInetAddr= *((struct sockaddr_in *)lpHostEnt->h_addr_list[0]);
//	}
//	return *this;
//}


CSocket::CSocket(int iDomain, int iType, int iProtocol)
{
	Init();
	m_iDomain = iDomain;
	Socket(iDomain, iType, iProtocol);

	m_eState = S_AVAILABLE;	
}

void CSocket::Socket(int iDomain, int iType, int iProtocol) throw(CSocketException)
{
				if ((m_iSocket = socket(iDomain, iType, iProtocol)) < 0)
#if defined(WIN32)
				throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
#else
				throw CSocketException(strerror(errno), __FILE__, __LINE__);
#endif
}

void CSocket::SockREUSEADDR()
{      
	
	int optval =1;
	if(setsockopt(m_iSocket, SOL_SOCKET, SO_REUSEADDR,(char*) &optval, sizeof(optval))!=0)
    #if defined(WIN32)
		throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
    #else
	throw CSocketException(strerror(errno), __FILE__, __LINE__);
    #endif

}

void CSocket::Init()
{
	m_iSocket = INVALID_SOCKET;
	m_eState = S_INITIAL;
	m_bBlock = true;
}

//use Shutdown(1) close write channel,All OS are same;
//use Shutdown(0)
//UNIX:    reflush the read queue,when has data receive,only ACK 
//WINDOWS: reset the link
int CSocket::Shutdown(int how) throw()
{

	return shutdown(m_iSocket,how);

}


void CSocket::End() throw()
{
	
	if (m_iSocket <=0 || (m_iSocket==INVALID_SOCKET) )
	{
		m_iSocket = INVALID_SOCKET;
		m_eState = S_INITIAL;
		return;
	}

    #if defined(WIN32)
	::closesocket(m_iSocket);
    #else
	::close(m_iSocket);
    #endif
	cerr<<"close "<<m_iSocket<<endl;
	m_iSocket = INVALID_SOCKET;
	m_eState = S_INITIAL;
}


void CSocket::SetBlock(bool bBlock) throw (CSocketException)
{
	#if defined(WIN32)
	int iFlag;
    u_long in_out_args;
    if(bBlock==false)
	{	
		in_out_args=1;
		iFlag=ioctlsocket(m_iSocket,FIONBIO ,&in_out_args);
		if(iFlag<0)
			throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
	}
	else
	{	
        in_out_args=0;
		iFlag=ioctlsocket(m_iSocket,FIONBIO ,&in_out_args);
		if(iFlag == SOCKET_ERROR)
			throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
	}
	
    #else
	int iFlag = fcntl(m_iSocket, F_GETFL);
	if (iFlag < 0)
		throw CSocketException(strerror(errno), __FILE__, __LINE__);

	if (bBlock)
		iFlag &= ~O_NONBLOCK;
	else
		iFlag |= O_NONBLOCK;
		
	if (fcntl(m_iSocket, F_SETFL, iFlag) < 0)
		throw CSocketException(strerror(errno), __FILE__, __LINE__);
    #endif		
	m_bBlock = bBlock;
}




void CSocket::ServerBind(const tcport_t tPort)
{
	struct sockaddr_in stSockAddr;
	memset(&stSockAddr, 0, sizeof(stSockAddr));
	stSockAddr.sin_family = AF_INET;
	stSockAddr.sin_port = htons(tPort);
	stSockAddr.sin_addr.s_addr = INADDR_ANY;

	m_InetAddr=stSockAddr;
	m_eState = S_BOUND;
	cerr<<"serv bound!\n";
	if (bind(m_iSocket, (struct sockaddr*)&stSockAddr, sizeof(stSockAddr)) < 0)
	#if defined(WIN32)
	throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
	#else
	throw CSocketException(strerror(errno), __FILE__, __LINE__);
	#endif	 
    
	//由系统分配端口,此时只有端口号可得
	if(tPort==0)
		StoreLocalIP_PORT();
}

void CSocket::SetMember(int socki,bool ifblock,CState st,int domaini)
{
	m_iSocket = socki;
    SetBlock(ifblock);
	m_eState = st;
    m_iDomain = domaini;
}


//服务器使用
CTcpSocket::CTcpSocket(const tcport_t tPort)
           : CSocket(AF_INET, SOCK_STREAM)
{
	ServerBind(tPort);
}

//客户端使用
CTcpSocket::CTcpSocket()
		: CSocket(AF_INET, SOCK_STREAM)
{

}


bool CTcpSocket::Accept(CSocket &connectsock)
{
	struct sockaddr_in stInetSockAddr;
	//struct sockaddr_un stUnixSockAddr;

    #if defined(WIN32)
	int tSockLen;
    #else
	socklen_t tSockLen;
    #endif

	sockaddr* pstSockAddr;
	pstSockAddr = (sockaddr*)&stInetSockAddr;
	tSockLen = sizeof(stInetSockAddr);

		
	while (true)
	{
		 #if defined(WIN32)
         			SOCKET i(INVALID_SOCKET)
		 #else
		              int i=-1;
		 #endif
			 i= accept(m_iSocket, pstSockAddr, /*(int*)*/&tSockLen);
			 cerr<<"acc "<<i<<'\n';
			#if defined(WIN32)
			 if (i == INVALID_SOCKET)
			 {
				 if (m_bBlock)
				 {
					 if (!OnAcceptIntr())
						 continue;
					 else
						 return false;
				 }
				 
				 if ( (!m_bBlock) && (WSAGetLastError()==WSAEWOULDBLOCK) )
					 return false;
				 
				 throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
				 
			#else
			 if (i < 0)
			 {
				if (m_bBlock && errno == EINTR)
				{
					if (!OnAcceptIntr())
						continue;
					else
						return false;
				}
					 
				if ( (!m_bBlock) && (errno == EWOULDBLOCK
					#ifdef ECONNABORTED
						 || errno == ECONNABORTED
					#endif
					#ifdef EPROTO
						 || errno == EPROTO
					#endif
						 ) )
						 return false;
					 
					 throw CSocketException(strerror(errno), __FILE__, __LINE__);
			#endif
			 }//end of "if (i == "
				 
				 //maybe reject special IP
		     if (!OnAccept(stInetSockAddr, ntohs(stInetSockAddr.sin_port)))
			 {
					#if defined(WIN32)
					 ::closesocket(m_iSocket);
					#else
					 ::close(m_iSocket);
					#endif
					 return false;
			 }
			 connectsock.SetMember(i,m_bBlock,S_CONNECTED,m_iDomain);
			 return true;
	}//end while
	return false;
}

/////////////////////////////////////////////////////////////////////////
// 函数名:AcceptwithTmOut
// 作  用:接受新连接。
// 参  数:CSocket &connectsock ,秒 nSec,毫秒 int nMs UNIX只能精确到10ms
// 返回值:超时:TIMEROUT_,成功返回0,错误返回负值,其他throw exception
// 修  改:
/////////////////////////////////////////////////////////////////////////
int CTcpSocket::AcceptwithTmOut(CSocket &connectsock,int nSec,int nMs)

⌨️ 快捷键说明

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