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

📄 socket.cpp

📁 贡献一份commoncpp2,有兴趣的可以研究一下
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// Copyright (C) 1999-2005 Open Source Telecom Corporation.//// 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.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// // As a special exception, you may use this file as part of a free software// library without restriction.  Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License.  This exception does not however    // invalidate any other reasons why the executable file might be covered by// the GNU General Public License.    //// This exception applies only to the code released under the name GNU// Common C++.  If you copy code from other releases into a copy of GNU// Common C++, as the General Public License permits, the exception does// not apply to the code that you add in this way.  To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU Common C++, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.//#include <cc++/config.h>#include <cc++/export.h>#include <cc++/exception.h>#include <cc++/thread.h>#include <cc++/address.h>#include <cc++/socket.h>#include "private.h"#include "nat.h"#include <fcntl.h>#include <cerrno>#include <cstdlib>#include <cstdarg>#include <cstdio>#ifndef	WIN32#include <netinet/tcp.h>#endif#ifdef	WIN32#include <io.h>#define socket_errno	WSAGetLastError()#endif#ifndef WIN32#include <sys/ioctl.h>#ifdef HAVE_NET_IP6_H#include <netinet/ip6.h>#endif#if defined(__hpux) && defined(_XOPEN_SOURCE_EXTENDED)#undef	_XOPEN_SOURCE_EXTENDED#endif#ifdef HAVE_NETINET_IN_H#include <netinet/in.h>#endif#if defined(__hpux)#define	_XOPEN_SOURCE_EXTENDED#endif#ifdef	HAVE_NET_IF_H#include <net/if.h>#endif#endif#ifndef	WIN32#define socket_errno errno# ifndef  O_NONBLOCK#  define O_NONBLOCK	O_NDELAY# endif# ifdef	IPPROTO_IP#  ifndef  SOL_IP#   define SOL_IP	IPPROTO_IP#  endif // !SOL_IP# endif	 // IPPROTO_IP#endif	 // !WIN32#ifndef	INADDR_LOOPBACK#define	INADDR_LOOPBACK	(unsigned long)0x7f000001#endif#ifdef	CCXX_NAMESPACESnamespace ost {using namespace std;#endif#if defined(WIN32) && !defined(__MINGW32__)static SOCKET dupSocket(SOCKET so,enum Socket::State state){	if (state == Socket::STREAM)		return dup((int)so);	HANDLE pidHandle = GetCurrentProcess();	HANDLE dupHandle;	if(DuplicateHandle(pidHandle, reinterpret_cast<HANDLE>(so), pidHandle, &dupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS))		return reinterpret_cast<SOCKET>(dupHandle);	return INVALID_SOCKET;}# define DUP_SOCK(s,state) dupSocket(s,state)#else# define DUP_SOCK(s,state) dup(s)#endif Mutex Socket::mutex;bool Socket::check(Family fam){	SOCKET so = INVALID_SOCKET;	switch(fam)	{	case IPV4:		so = socket(fam, SOCK_DGRAM, IPPROTO_UDP);		break;#ifdef	CCXX_IPV6	case IPV6:		so = socket(fam, SOCK_DGRAM, IPPROTO_UDP);		break;#endif	}	if(so == INVALID_SOCKET)		return false;#ifdef	WIN32	closesocket(so);#else	close(so);#endif	return true;}Socket::Socket(){	setSocket();}Socket::Socket(int domain, int type, int protocol){	setSocket();	so = socket(domain, type, protocol);	if(so == INVALID_SOCKET)	{		error(errCreateFailed,"Could not create socket",socket_errno);		return;	}#ifdef	SO_NOSIGPIPE	int opt = 1;	setsockopt(so, SOL_SOCKET, SO_NOSIGPIPE, (char *)&opt, sizeof(opt));#endif	state = AVAILABLE;}Socket::Socket(SOCKET fd){	setSocket();	if (fd == INVALID_SOCKET)	{		error(errCreateFailed,"Invalid socket handle passed",0);		return;	}	so = fd;	state = AVAILABLE;}Socket::Socket(const Socket &orig){	setSocket();	so = DUP_SOCK(orig.so,orig.state);	if(so == INVALID_SOCKET)		error(errCopyFailed,"Could not duplicate socket handle",socket_errno);	state = orig.state;}Socket::~Socket(){	endSocket();}void Socket::setSocket(void){	flags.thrown    = false;	flags.broadcast = false;	flags.route     = true;	flags.keepalive = false;	flags.loopback  = true;	flags.multicast = false;	flags.linger	= false;	flags.ttl	= 1;	errid           = errSuccess;	errstr          = NULL;	syserr          = 0;	state           = INITIAL;	so              = INVALID_SOCKET;}Socket::Error Socket::sendLimit(int limit){#ifdef	SO_SNDLOWAT	if(setsockopt(so, SOL_SOCKET, SO_SNDLOWAT, (char *)&limit, sizeof(limit)))		return errInvalidValue;	return errSuccess;	#else	return errServiceUnavailable;#endif}Socket::Error Socket::receiveLimit(int limit){#ifdef  SO_RCVLOWAT        if(setsockopt(so, SOL_SOCKET, SO_RCVLOWAT, (char *)&limit, sizeof(limit)))                return errInvalidValue;        return errSuccess;#else        return errServiceUnavailable;#endif}Socket::Error Socket::sendTimeout(timeout_t to){#ifdef  SO_SNDTIMEO        struct timeval tv;        tv.tv_sec = to / 1000;        tv.tv_usec = (to % 1000) * 1000;        if(setsockopt(so, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)))                return errInvalidValue;        return errSuccess;#else        return errServiceUnavailable;#endif}Socket::Error Socket::receiveTimeout(timeout_t to){#ifdef  SO_RCVTIMEO        struct timeval tv;        tv.tv_sec = to / 1000;        tv.tv_usec = (to % 1000) * 1000;        if(setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)))                return errInvalidValue;        return errSuccess;#else        return errServiceUnavailable;#endif}	Socket::Error Socket::sendBuffer(unsigned bufsize){#ifdef	SO_SNDBUF	if(setsockopt(so, SOL_SOCKET, SO_SNDBUF, (char *)&bufsize, sizeof(bufsize)))		return errInvalidValue;	return errSuccess;#else	return errServiceUnavailable;#endif}		Socket::Error Socket::bufferSize(unsigned bufsize){	Error err = receiveBuffer(bufsize);	if(err == errSuccess)		err = sendBuffer(bufsize);	return err;}Socket::Error Socket::receiveBuffer(unsigned bufsize){#ifdef  SO_RCVBUF        if(setsockopt(so, SOL_SOCKET, SO_RCVBUF, (char *)&bufsize, sizeof(bufsize)))		return errInvalidValue;        return errSuccess;#else        return errServiceUnavailable; #endif}ssize_t Socket::readLine(char *str, size_t request, timeout_t timeout){	bool crlf = false;	bool nl = false;	size_t nleft = request - 1; // leave also space for terminator	int nstat,c;	if(request < 1)		return 0;	str[0] = 0;	while(nleft && !nl)	{		if(timeout)		{			if(!isPending(pendingInput, timeout))			{				error(errTimeout,"Read timeout", 0);				return -1;			}		}		nstat = ::recv(so, str, _IOLEN64 nleft, MSG_PEEK);		if(nstat <= 0)		{			error(errInput,"Could not read from socket", socket_errno);			return -1;		}		// FIXME: if unique char in buffer is '\r' return "\r"		//        if buffer end in \r try to read another char?		//        and if timeout ??		//        remember last \r		for(c=0; c < nstat; ++c)		{			if(str[c] == '\n')			{				if (c > 0 && str[c-1] == '\r')					crlf = true;				++c;				nl = true;				break;			}		}		nstat = ::recv(so, str, c, 0);		// TODO: correct ???		if(nstat < 0)			break;		// adjust ending \r\n in \n		if(crlf)		{			--nstat;			str[nstat - 1] = '\n';		}		str += nstat;		nleft -= nstat;	}	*str = 0;	return (ssize_t)(request - nleft - 1);}ssize_t Socket::readData(void *Target, size_t Size, char Separator, timeout_t timeout){  if ((Separator == 0x0D) || (Separator == 0x0A))    return (readLine ((char *) Target, Size, timeout));  if (Size < 1)    return (0);  ssize_t nstat;  if (Separator == 0)           // Flat-out read for a number of bytes.    {      if (timeout)        if (!isPending (pendingInput, timeout))          {            error(errTimeout);            return (-1);          }      nstat =::recv (so, (char *)Target, _IOLEN64 Size, 0);      if (nstat < 0)        {          error (errInput);          return (-1);        }      return (nstat);    }  /////////////////////////////////////////////////////////////  // Otherwise, we have a special char separator to use  /////////////////////////////////////////////////////////////  bool found = false;  size_t nleft = Size;  int c;  char *str = (char *) Target;  memset (str, 0, Size);  while (nleft && !found)    {      if (timeout)        if (!isPending (pendingInput, timeout))          {            error(errTimeout);            return (-1);          }      nstat =::recv (so, str, _IOLEN64 nleft, MSG_PEEK);      if (nstat <= 0)        {          error (errInput);          return (-1);        }      for (c = 0; (c < nstat) && !found; ++c)        if (str[c] == Separator)          found = true;      memset (str, 0, nleft);       nstat =::recv (so, str, c, 0);      if (nstat < 0)        break;      str += nstat;      nleft -= nstat;    }  return (ssize_t)(Size - (ssize_t) nleft);}ssize_t Socket::writeData(const void *Source, size_t Size, timeout_t timeout){  if (Size < 1)    return (0);  ssize_t nstat;  const char *Slide = (const char *) Source;  while (true)    {      if (timeout)        if (!isPending (pendingOutput, timeout))          {            error(errOutput);            return (-1);          }      nstat =::send (so, Slide, _IOLEN64 Size, 0);      if (nstat <= 0)        {          error(errOutput);          return (-1);        }      Size -= nstat;      Slide += Size;      if (Size <= 0)        break;    }  return (nstat);}bool Socket::isConnected(void) const{	return (Socket::state == CONNECTED) ? true : false;}bool Socket::isActive(void) const{	return (state != INITIAL) ? true : false;}bool Socket::operator!() const{	return (Socket::state == INITIAL) ? true : false;}void Socket::endSocket(void){	if(Socket::state == STREAM)	{		state = INITIAL;#ifdef	WIN32		if(so != (UINT)-1)		{			SOCKET sosave = so;			so = INVALID_SOCKET;			closesocket((int)sosave);		}#else		if(so > -1)		{			SOCKET sosave = so;			so = INVALID_SOCKET;			close(sosave);		}#endif		return;	}	state = INITIAL;	if(so == INVALID_SOCKET)		return;#ifdef	SO_LINGER	struct linger linger;	if(flags.linger)	{		linger.l_onoff = 1;		linger.l_linger = 60;	}	else		linger.l_onoff = linger.l_linger = 0;	setsockopt(so, SOL_SOCKET, SO_LINGER, (char *)&linger,		(socklen_t)sizeof(linger));#endif//	shutdown(so, 2);#ifdef WIN32	closesocket(so);#else	close(so);#endif	so = INVALID_SOCKET;}#ifdef WIN32Socket::Error Socket::connectError(void){	char* str = "Could not connect to remote host";	switch(WSAGetLastError())	{	case WSAENETDOWN:		return error(errResourceFailure,str,socket_errno);	case WSAEINPROGRESS:		return error(errConnectBusy,str,socket_errno);	case WSAEADDRNOTAVAIL:		return error(errConnectInvalid,str,socket_errno);	case WSAECONNREFUSED:		return error(errConnectRefused,str,socket_errno);	case WSAENETUNREACH:		return error(errConnectNoRoute,str,socket_errno);	default:		return error(errConnectFailed,str,socket_errno);	}}#elseSocket::Error Socket::connectError(void){	char* str = "Could not connect to remote host";	switch(errno)	{#ifdef	EHOSTUNREACH	case EHOSTUNREACH:		return error(errConnectNoRoute,str,socket_errno);#endif#ifdef	ENETUNREACH	case ENETUNREACH:		return error(errConnectNoRoute,str,socket_errno);#endif	case EINPROGRESS:		return error(errConnectBusy,str,socket_errno);#ifdef	EADDRNOTAVAIL	case EADDRNOTAVAIL:		return error(errConnectInvalid,str,socket_errno);#endif	case ECONNREFUSED:		return error(errConnectRefused,str,socket_errno);	case ETIMEDOUT:		return error(errConnectTimeout,str,socket_errno);	default:		return error(errConnectFailed,str,socket_errno);	}}#endifSocket::Error Socket::error(Error err, char *errs, long systemError) const{	errid  = err;	errstr = errs;	syserr = systemError;	if(!err)		return err;	if(flags.thrown)		return err;	// prevents recursive throws	flags.thrown = true;#ifdef	CCXX_EXCEPTIONS	switch(Thread::getException())	{	case Thread::throwObject:		throw((Socket *)this);#ifdef	COMMON_STD_EXCEPTION	case Thread::throwException:		{			if(!errs)				errs = "";			throw SockException(String(errs), err, systemError);		}#endif	case Thread::throwNothing:		break;	}#endif	return err;}const char *Socket::getSystemErrorString(void) const{#ifdef	CCXX_EXCEPTIONS	SockException e(errstr, errid, syserr);	return e.getSystemErrorString();#else	return NULL;#endif}Socket::Error Socket::setBroadcast(bool enable){	int opt = (enable ? 1 : 0);	if(setsockopt(so, SOL_SOCKET, SO_BROADCAST,		      (char *)&opt, (socklen_t)sizeof(opt)))		return error(errBroadcastDenied,"Could not set socket broadcast option",socket_errno);	flags.broadcast = enable;	return errSuccess;

⌨️ 快捷键说明

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