示例#1
0
//------------------------------------------------------------------------------
//
// Open() - Create a connection to a specified address on a specified port
//
//------------------------------------------------------------------------------
bool CActiveSocket::Open(const char *pAddr, uint16 nPort)
{
    bool bRetVal = false;

    if (IsSocketValid() == false)
    {
        SetSocketError(CSimpleSocket::SocketInvalidSocket);
        return bRetVal;
    }

    if (pAddr == NULL)
    {
        SetSocketError(CSimpleSocket::SocketInvalidAddress);
        return bRetVal;
    }

    if (nPort == 0)
    {
        SetSocketError(CSimpleSocket::SocketInvalidPort);
        return bRetVal;
    }

    switch (m_nSocketType)
    {
    case CSimpleSocket::SocketTypeTcp :
    {
        bRetVal = ConnectTCP(pAddr, nPort);
        break;
    }
    case CSimpleSocket::SocketTypeUdp :
    {
        bRetVal = ConnectUDP(pAddr, nPort);
        break;
    }
    case CSimpleSocket::SocketTypeRaw :
        break;
    default:
        break;
    }

    //--------------------------------------------------------------------------
    // If successful then create a local copy of the address and port
    //--------------------------------------------------------------------------
    if (bRetVal)
    {
        socklen_t nSockLen = sizeof(struct sockaddr);

        memset(&m_stServerSockaddr, 0, nSockLen);
        getpeername(m_socket, (struct sockaddr *)&m_stServerSockaddr, &nSockLen);

        nSockLen = sizeof(struct sockaddr);
        memset(&m_stClientSockaddr, 0, nSockLen);
        getsockname(m_socket, (struct sockaddr *)&m_stClientSockaddr, &nSockLen);

        SetSocketError(SocketSuccess);
    }

    return bRetVal;
}
示例#2
0
//------------------------------------------------------------------------------
//
// Send() - Send data on a valid socket
//
//------------------------------------------------------------------------------
int32 CPassiveSocket::Send(const uint8 *pBuf, size_t bytesToSend)
{
    SetSocketError(SocketSuccess);
    m_nBytesSent = 0;

    switch(m_nSocketType)
    {
       case CSimpleSocket::SocketTypeUdp:
        {
            if (IsSocketValid())
            {
                if ((bytesToSend > 0) && (pBuf != NULL))
                {
                    m_timer.Initialize();
                    m_timer.SetStartTime();

                    m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stClientSockaddr, sizeof(m_stClientSockaddr));

                    m_timer.SetEndTime();

                    if (m_nBytesSent == CSimpleSocket::SocketError)
                    {
                        TranslateSocketError();
                    }
                }
            }
            break;
        }
       default:
           CSimpleSocket::Send(pBuf, bytesToSend);
           break;
    }

    return m_nBytesSent;
}
//------------------------------------------------------------------------------
//
// Select()
//
//------------------------------------------------------------------------------
bool TDSocket::Select(i32 nTimeoutSec, i32 nTimeoutUSec)
{
	bool            bRetVal = false;
	struct timeval *pTimeout = NULL;
	struct timeval  timeout;
	i32           nNumDescriptors = -1;
	i32           nError = 0;

	FD_ZERO(&m_errorFds);
	FD_ZERO(&m_readFds);
	FD_ZERO(&m_writeFds);
	FD_SET(m_socket, &m_errorFds);
	FD_SET(m_socket, &m_readFds);
	FD_SET(m_socket, &m_writeFds);

	//---------------------------------------------------------------------
	// If timeout has been specified then set value, otherwise set timeout
	// to NULL which will block until a descriptor is ready for read/write
	// or an error has occurred.
	//---------------------------------------------------------------------
	if ((nTimeoutSec >= 0) || (nTimeoutUSec >= 0))
	{
		timeout.tv_sec = nTimeoutSec;
		timeout.tv_usec = nTimeoutUSec;
		pTimeout = &timeout;
	}

	nNumDescriptors = SELECT(m_socket + 1, &m_readFds, &m_writeFds, &m_errorFds, pTimeout);
	//    nNumDescriptors = SELECT(m_socket+1, &m_readFds, NULL, NULL, pTimeout);

	//----------------------------------------------------------------------
	// Handle timeout
	//----------------------------------------------------------------------
	if (nNumDescriptors == 0)
	{
		SetSocketError(TDSocket::SocketTimedout);
	}
	//----------------------------------------------------------------------
	// If a file descriptor (read/write) is set then check the
	// socket error (SO_ERROR) to see if there is a pending error.
	//----------------------------------------------------------------------
	else if ((FD_ISSET(m_socket, &m_readFds)) || (FD_ISSET(m_socket, &m_writeFds)))
	{
		i32 nLen = sizeof(nError);

		if (GETSOCKOPT(m_socket, SOL_SOCKET, SO_ERROR, &nError, &nLen) == 0)
		{
			errno = nError;

			if (nError == 0)
			{
				bRetVal = true;
			}
		}

		TranslateSocketError();
	}

	return bRetVal;
}
示例#4
0
bool CSocket::Connect(const char* ip,int port)
{
	isConnected=true;
	socketError=SocketEnum::Success;
	if(WSAStartup(MAKEWORD(2,2),&wsa)!=0)//初始化套接字DLL
	{
		SetSocketError(SocketEnum::WSAStartupError); 
		isConnected=false;
	}

	if(isConnected)
	{
		if((csocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){
			SetSocketError();
			isConnected=false;
		}
	}

	if(isConnected){
		memset(&serverAddress,0,sizeof(sockaddr_in));
		serverAddress.sin_family=AF_INET;
		long lip=inet_addr(ip);
		if(lip==INADDR_NONE)
		{ 
			SetSocketError(SocketEnum::InvalidAddress); 
		    isConnected=false;
		} else{
			if(port<0)
			{
				SetSocketError(SocketEnum::InvalidPort);
				isConnected=false;
			}else{
				serverAddress.sin_addr.S_un.S_addr= lip;
				serverAddress.sin_port = htons(port);
				if(connect(csocket,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR){
					SetSocketError(); 
					isConnected=false;
				} 
			}
		}
	}
 
	return isConnected; 
}
//------------------------------------------------------------------------------
//
// Send() - Send data on a valid socket via a vector of buffers.
//
//------------------------------------------------------------------------------
i32 TDSocket::Send(const struct iovec *sendVector, i32 nNumItems)
{
	SetSocketError(SocketSuccess);
	m_nBytesSent = 0;

	if ((m_nBytesSent = WRITEV(m_socket, sendVector, nNumItems)) == TDSocket::SocketError)
	{
		TranslateSocketError();
	}

	return m_nBytesSent;
}
示例#6
0
//------------------------------------------------------------------------------
//
// ConnectUDP() -
//
//------------------------------------------------------------------------------
bool CActiveSocket::ConnectUDP(const char *pAddr, uint16 nPort)
{
    bool           bRetVal = false;
    struct in_addr stIpAddress;

    //------------------------------------------------------------------
    // Pre-connection setup that must be preformed
    //------------------------------------------------------------------
    memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));
    m_stServerSockaddr.sin_family = AF_INET;

    if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL)
    {
#ifdef WIN32
        TranslateSocketError();
#else
        if (h_errno == HOST_NOT_FOUND)
        {
            SetSocketError(SocketInvalidAddress);
        }
#endif
        return bRetVal;
    }

    memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length);
    m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;

    if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError)
    {
        TranslateSocketError();
        return bRetVal;
    }

    m_stServerSockaddr.sin_port = htons(nPort);

    //------------------------------------------------------------------
    // Connect to address "xxx.xxx.xxx.xxx"    (IPv4) address only.
    //
    //------------------------------------------------------------------
    m_timer.Initialize();
    m_timer.SetStartTime();

    if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError)
    {
        bRetVal = true;
    }

    TranslateSocketError();

    m_timer.SetEndTime();

    return bRetVal;
}
示例#7
0
//------------------------------------------------------------------------------
//
// Accept() - 
//
//------------------------------------------------------------------------------
CActiveSocket *CPassiveSocket::Accept(uint32_t timeout_sec)
{
    uint32_t         nSockLen;
	std::auto_ptr<CActiveSocket> ClientSocket;
    SOCKET         socket = CSimpleSocket::SocketError;

    if (m_nSocketType != CSimpleSocket::SocketTypeTcp) {
        SetSocketError(CSimpleSocket::SocketProtocolError);
        return 0;
    }

    ClientSocket.reset (new CActiveSocket(m_compress_, m_nSocketType));

    //--------------------------------------------------------------------------
    // Wait for incoming connection.
    //--------------------------------------------------------------------------
    CSocketError socketErrno = SocketSuccess;
    nSockLen = sizeof(m_stClientSockaddr);
    do {
        errno = 0;
		if (!Select (timeout_sec, 0))
			return 0;

		socket = accept(m_socket, (struct sockaddr *)&m_stClientSockaddr, (socklen_t *)&nSockLen);
        if (socket != -1) {
            ClientSocket->SetSocketHandle(socket);
            ClientSocket->TranslateSocketError();
            socketErrno = ClientSocket->GetSocketError();
            socklen_t nSockLen = sizeof(struct sockaddr);

            //-------------------------------------------------------------
            // Store client and server IP and port information for this
            // connection.
            //-------------------------------------------------------------
            getpeername(m_socket, (struct sockaddr *)&ClientSocket->m_stClientSockaddr, &nSockLen);
            memcpy((void *)&ClientSocket->m_stClientSockaddr, (void *)&m_stClientSockaddr, nSockLen);

            memset(&ClientSocket->m_stServerSockaddr, 0, nSockLen);
            getsockname(m_socket, (struct sockaddr *)&ClientSocket->m_stServerSockaddr, &nSockLen);
        }
        else {
            TranslateSocketError();
            socketErrno = GetSocketError();
        }
    } while (socketErrno == CSimpleSocket::SocketInterrupted);
    
    if (socketErrno != CSimpleSocket::SocketSuccess)
		return 0;

	return ClientSocket.release ();
}
//------------------------------------------------------------------------------
//
// ConnectRAW() -
//
//------------------------------------------------------------------------------
bool TDSocket::ConnectRAW(const char *pAddr, i16 nPort)
{
	bool           bRetVal = false;
	struct in_addr stIpAddress;
	//------------------------------------------------------------------
	// Pre-connection setup that must be preformed					 
	//------------------------------------------------------------------
	memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));
	m_stServerSockaddr.sin_family = AF_INET;

	hostent * pHE = NULL;
	if ((pHE = GETHOSTBYNAME(pAddr)) == NULL)
	{
#ifdef WIN32
		TranslateSocketError();
#else
		if (h_errno == HOST_NOT_FOUND)
		{
			SetSocketError(SocketInvalidAddress);
		}
#endif
		return bRetVal;
	}

	memcpy(&stIpAddress, pHE->h_addr_list[0], pHE->h_length);
	m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;

	if ((i32)m_stServerSockaddr.sin_addr.s_addr == TDSocket::SocketError)
	{
		TranslateSocketError();
		return bRetVal;
	}

	m_stServerSockaddr.sin_port = htons(nPort);

	//------------------------------------------------------------------
	// Connect to address "xxx.xxx.xxx.xxx"	(IPv4) address only.  
	// 
	//------------------------------------------------------------------

	if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != TDSocket::SocketError)
	{
		bRetVal = true;
	}

	TranslateSocketError();


	return bRetVal;
}
示例#9
0
//------------------------------------------------------------------------------
//
// Close() - Close socket and free up any memory allocated for the socket
//
//------------------------------------------------------------------------------
bool CPassiveSocket::Close(void)
{
    if (IsSocketValid())
    {
        if (shutdown(m_socket, CSimpleSocket::Both) != CSimpleSocket::SocketError)
        {
            if (CLOSE(m_socket) != CSimpleSocket::SocketError)
            {
                m_socket = CSimpleSocket::SocketError;
                SetSocketError(CSimpleSocket::SocketInvalidSocket);
                return true;
            }
        }
    }

    TranslateSocketError();

    return false;
}
示例#10
0
int CSocket::Receive(int strLen)
{
	recvCount=0;
	if(!IsSocketValid() || !isConnected)
	{
		return recvCount;
	} 
	if(strLen<1)
	{
		return recvCount;
	} 
	if(buffer!=NULL)
	{
		delete buffer;
		buffer=NULL;
	} 
	buffer=new char[strLen];
	SetSocketError(SocketEnum::Success); 
	while(1){
		cout << "wait rec" << endl;
		recvCount=recv(csocket,buffer,strLen,0) ; 
		cout << "rec over" << endl;
		if(recvCount>0){
			buffer[recvCount]='\0';
			if(IsExit())
			{
				Send(buffer,recvCount);
				delete buffer;
				buffer=NULL;
				recvCount=0; 
				break;
			}else{
				for (int i = 0; i < recvCount; i++)
				{
					cout << buffer[i] << endl;
				}
				cout<<buffer<<endl;
			}
		}
	}
	 
	return recvCount;
}
//------------------------------------------------------------------------------
//
// SetWindowSize()
//
//------------------------------------------------------------------------------
u16 TDSocket::SetWindowSize(u32 nOptionName, u32 nWindowSize)
{
	u32 nRetVal = 0;

	//-------------------------------------------------------------------------
	// no socket given, return system default allocate our own new socket
	//-------------------------------------------------------------------------
	if (m_socket != TDSocket::SocketError)
	{
		nRetVal = SETSOCKOPT(m_socket, SOL_SOCKET, nOptionName, &nWindowSize, sizeof(nWindowSize));
		TranslateSocketError();
	}
	else
	{
		SetSocketError(TDSocket::SocketInvalidSocket);
	}

	return (u16)nWindowSize;
}
//------------------------------------------------------------------------------
//
// BindInterface()
//
//------------------------------------------------------------------------------
bool TDSocket::BindInterface(u8 *pInterface)
{
	bool           bRetVal = false;
	struct in_addr stInterfaceAddr;

	if (GetMulticast() == true)
	{
		if (pInterface)
		{
			stInterfaceAddr.s_addr = inet_addr((const char *)pInterface);
			if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_MULTICAST_IF, &stInterfaceAddr, sizeof(stInterfaceAddr)) == SocketSuccess)
			{
				bRetVal = true;
			}
		}
	}
	else
	{
		SetSocketError(TDSocket::SocketProtocolError);
	}

	return bRetVal;
}
//------------------------------------------------------------------------------
//
// GetWindowSize() 
//
//------------------------------------------------------------------------------
u16 TDSocket::GetWindowSize(u32 nOptionName)
{
	u32 nTcpWinSize = 0;

	//-------------------------------------------------------------------------
	// no socket given, return system default allocate our own new socket
	//-------------------------------------------------------------------------
	if (m_socket != TDSocket::SocketError)
	{
		socklen_t nLen = sizeof(nTcpWinSize);

		//---------------------------------------------------------------------
		// query for buffer size 
		//---------------------------------------------------------------------
		GETSOCKOPT(m_socket, SOL_SOCKET, nOptionName, &nTcpWinSize, &nLen);
		TranslateSocketError();
	}
	else
	{
		SetSocketError(TDSocket::SocketInvalidSocket);
	}

	return nTcpWinSize;
}
示例#14
0
//------------------------------------------------------------------------------
//
// Accept() - 
//
//------------------------------------------------------------------------------
CActiveSocket *CPassiveSocket::Accept()
{
    uint32         nSockLen;
    CActiveSocket *pClientSocket = NULL;
    SOCKET         socket = CSimpleSocket::SocketError;

    if (m_nSocketType != CSimpleSocket::SocketTypeTcp)
    {
        SetSocketError(CSimpleSocket::SocketProtocolError);
        return pClientSocket;
    }

    pClientSocket = new CActiveSocket();

    //--------------------------------------------------------------------------
    // Wait for incoming connection.
    //--------------------------------------------------------------------------
    if (pClientSocket != NULL)
    {
        CSocketError socketErrno = SocketSuccess;

        m_timer.Initialize();
        m_timer.SetStartTime();
        
        nSockLen = sizeof(m_stClientSockaddr);
        
        do
        {
            errno = 0;
            socket = accept(m_socket, (struct sockaddr *)&m_stClientSockaddr, (socklen_t *)&nSockLen);

            if (socket != -1)
            {
                pClientSocket->SetSocketHandle(socket);
                pClientSocket->TranslateSocketError();
                socketErrno = pClientSocket->GetSocketError();
                socklen_t nSockLen = sizeof(struct sockaddr);

                //-------------------------------------------------------------
                // Store client and server IP and port information for this
                // connection.
                //-------------------------------------------------------------
                getpeername(m_socket, (struct sockaddr *)&pClientSocket->m_stClientSockaddr, &nSockLen);
                memcpy((void *)&pClientSocket->m_stClientSockaddr, (void *)&m_stClientSockaddr, nSockLen);

                memset(&pClientSocket->m_stServerSockaddr, 0, nSockLen);
                getsockname(m_socket, (struct sockaddr *)&pClientSocket->m_stServerSockaddr, &nSockLen);
            }
            else
            {
                TranslateSocketError();
                socketErrno = GetSocketError();
            }

        } while (socketErrno == CSimpleSocket::SocketInterrupted);
        
        m_timer.SetEndTime();
        
        if (socketErrno != CSimpleSocket::SocketSuccess)
        {
            delete pClientSocket;
            pClientSocket = NULL;
        }
    }

    return pClientSocket;
}
示例#15
0
Status::Status(sf::Socket::Status _socket_status) : Status() {
  SetSocketError(_socket_status);
}
//------------------------------------------------------------------------------
//
// TranslateSocketError() -					
//
//------------------------------------------------------------------------------
void TDSocket::TranslateSocketError(void)
{
#ifndef WIN32
	switch (errno)
	{
	case EXIT_SUCCESS:
		SetSocketError(TDSocket::SocketSuccess);
		break;
	case ENOTCONN:
		SetSocketError(TDSocket::SocketNotconnected);
		break;
	case ENOTSOCK:
	case EBADF:
	case EACCES:
	case EAFNOSUPPORT:
	case EMFILE:
	case ENFILE:
	case ENOBUFS:
	case ENOMEM:
	case EPROTONOSUPPORT:
		SetSocketError(TDSocket::SocketInvalidSocket);
		break;
	case ECONNREFUSED:
		SetSocketError(TDSocket::SocketConnectionRefused);
		break;
	case ETIMEDOUT:
		SetSocketError(TDSocket::SocketTimedout);
		break;
	case EINPROGRESS:
		SetSocketError(TDSocket::SocketEinprogress);
		break;
	case EWOULDBLOCK:
		//		case EAGAIN:
		SetSocketError(TDSocket::SocketEwouldblock);
		break;
	case EINTR:
		SetSocketError(TDSocket::SocketInterrupted);
		break;
	case ECONNABORTED:
		SetSocketError(TDSocket::SocketConnectionAborted);
		break;
	case EINVAL:
	case EPROTO:
		SetSocketError(TDSocket::SocketProtocolError);
		break;
	case EPERM:
		SetSocketError(TDSocket::SocketFirewallError);
		break;
	case EFAULT:
		SetSocketError(TDSocket::SocketInvalidSocketBuffer);
		break;
	case ECONNRESET:
		SetSocketError(TDSocket::SocketConnectionReset);
		break;
	case ENOPROTOOPT:
		SetSocketError(TDSocket::SocketConnectionReset);
		break;
	default:
		SetSocketError(TDSocket::SocketEunknown);
		break;
	}
#endif
#ifdef WIN32
	i32 nError = WSAGetLastError();
	switch (nError)
	{
	case EXIT_SUCCESS:
		SetSocketError(TDSocket::SocketSuccess);
		break;
	case WSAEBADF:
	case WSAENOTCONN:
		SetSocketError(TDSocket::SocketNotconnected);
		break;
	case WSAEINTR:
		SetSocketError(TDSocket::SocketInterrupted);
		break;
	case WSAEACCES:
	case WSAEAFNOSUPPORT:
	case WSAEINVAL:
	case WSAEMFILE:
	case WSAENOBUFS:
	case WSAEPROTONOSUPPORT:
		SetSocketError(TDSocket::SocketInvalidSocket);
		break;
	case WSAECONNREFUSED:
		SetSocketError(TDSocket::SocketConnectionRefused);
		break;
	case WSAETIMEDOUT:
		SetSocketError(TDSocket::SocketTimedout);
		break;
	case WSAEINPROGRESS:
		SetSocketError(TDSocket::SocketEinprogress);
		break;
	case WSAECONNABORTED:
		SetSocketError(TDSocket::SocketConnectionAborted);
		break;
	case WSAEWOULDBLOCK:
		SetSocketError(TDSocket::SocketEwouldblock);
		break;
	case WSAENOTSOCK:
		SetSocketError(TDSocket::SocketInvalidSocket);
		break;
	case WSAECONNRESET:
		SetSocketError(TDSocket::SocketConnectionReset);
		break;
	case WSANO_DATA:
		SetSocketError(TDSocket::SocketInvalidAddress);
		break;
	case WSAEADDRINUSE:
		SetSocketError(TDSocket::SocketAddressInUse);
		break;
	case WSAEFAULT:
		SetSocketError(TDSocket::SocketInvalidPointer);
		break;
	default:
		SetSocketError(TDSocket::SocketEunknown);
		break;
	}
#endif
}
//------------------------------------------------------------------------------
//
// Receive() - Attempts to receive a block of data on an established		
//			   connection.	Data is received in an internal buffer managed	
//			   by the class.  This buffer is only valid until the next call	
//			   to Receive(), a call to Close(), or until the object goes out
//			   of scope.													
//																			
//------------------------------------------------------------------------------
i32 TDSocket::Receive(i32 nMaxBytes)
{
	m_nBytesReceived = 0;

	//--------------------------------------------------------------------------
	// If the socket is invalid then return false.
	//--------------------------------------------------------------------------
	if (IsSocketValid() == false)
	{
		return m_nBytesReceived;
	}

	//--------------------------------------------------------------------------
	// Free existing buffer and allocate a new buffer the size of
	// nMaxBytes.
	//--------------------------------------------------------------------------
	if (nMaxBytes != m_nBufferSize)
	{
		m_nBufferSize = nMaxBytes;
		m_pBuffer.clear();
		m_pBuffer.resize(m_nBufferSize);
	}

	SetSocketError(SocketSuccess);

	switch (m_nSocketType)
	{
		//----------------------------------------------------------------------
		// If zero bytes are received, then return.  If SocketERROR is 
		// received, free buffer and return CSocket::SocketError (-1) to caller.	
		//----------------------------------------------------------------------
	case TDSocket::SocketTypeTcp:
	{
		do
		{
			m_nBytesReceived = RECV(m_socket, &m_pBuffer[m_nBytesReceived],
				nMaxBytes - m_nBytesReceived, m_nFlags);
			TranslateSocketError();
		} while (IsSocketValid() && (GetSocketError() == TDSocket::SocketInterrupted));

		break;
	}
	case TDSocket::SocketTypeUdp:
	{
		socklen_t srcSize;

		srcSize = sizeof(struct sockaddr_in);

		if (GetMulticast() == true)
		{
			do
			{
				m_nBytesReceived = RECVFROM(m_socket, &m_pBuffer[0], nMaxBytes, 0,
					&m_stMulticastGroup, &srcSize);
				TranslateSocketError();
			} while (IsSocketValid() && GetSocketError() == TDSocket::SocketInterrupted);
		}
		else
		{
			do
			{
				m_nBytesReceived = RECVFROM(m_socket, &m_pBuffer[0], nMaxBytes, 0,
					&m_stClientSockaddr, &srcSize);
				TranslateSocketError();
			} while (GetSocketError() == TDSocket::SocketInterrupted);
		}

		break;
	}
	default:
		break;
	}

	TranslateSocketError();
	return m_nBytesReceived;
}
示例#18
0
//------------------------------------------------------------------------------
//
// Listen() -
//
//------------------------------------------------------------------------------
bool CPassiveSocket::Listen(const char *pAddr, uint16 nPort, int32 nConnectionBacklog)
{
    bool           bRetVal = false;
#ifdef WIN32
    ULONG          inAddr;
#else
    in_addr_t      inAddr;

    int32          nReuse;
    nReuse = IPTOS_LOWDELAY;

    //--------------------------------------------------------------------------
    // Set the following socket option SO_REUSEADDR.  This will allow the file
    // descriptor to be reused immediately after the socket is closed instead
    // of setting in a TIMED_WAIT state.
    //--------------------------------------------------------------------------
    SETSOCKOPT(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&nReuse, sizeof(int32));
    SETSOCKOPT(m_socket, IPPROTO_TCP, IP_TOS, &nReuse, sizeof(int32));
#endif

    memset(&m_stServerSockaddr,0,sizeof(m_stServerSockaddr));
    m_stServerSockaddr.sin_family = AF_INET;
    m_stServerSockaddr.sin_port = htons(nPort);

    //--------------------------------------------------------------------------
    // If no IP Address (interface ethn) is supplied, or the loop back is
    // specified then bind to any interface, else bind to specified interface.
    //--------------------------------------------------------------------------
    if ((pAddr == NULL) || (!strlen(pAddr)))
    {
        m_stServerSockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    }
    else
    {
        if ((inAddr = inet_addr(pAddr)) != INADDR_NONE)
        {
            m_stServerSockaddr.sin_addr.s_addr = inAddr;
        }
    }

    m_timer.Initialize();
    m_timer.SetStartTime();

    //--------------------------------------------------------------------------
    // Bind to the specified port
    //--------------------------------------------------------------------------
    if (bind(m_socket, (struct sockaddr *)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError)
    {
        if (m_nSocketType == CSimpleSocket::SocketTypeTcp)
        {
            if (listen(m_socket, nConnectionBacklog) != CSimpleSocket::SocketError)
            {
                bRetVal = true;
            }
        }
        else
        {
            bRetVal = true;
        }
    }

    m_timer.SetEndTime();

    //--------------------------------------------------------------------------
    // If there was a socket error then close the socket to clean out the
    // connection in the backlog.
    //--------------------------------------------------------------------------
    TranslateSocketError();

    if (bRetVal == false)
    {
        CSocketError err = GetSocketError();
        Close();
        SetSocketError(err);
    }

    return bRetVal;
}
//------------------------------------------------------------------------------
//
// Send() - Send data on a valid socket
//
//------------------------------------------------------------------------------
i32 TDSocket::Send(const char *pBuf, size_t bytesToSend)
{
	SetSocketError(SocketSuccess);
	m_nBytesSent = 0;

	switch (m_nSocketType)
	{
	case TDSocket::SocketTypeTcp:
	{
		if (IsSocketValid())
		{
			if ((bytesToSend > 0) && (pBuf != NULL))
			{
				//---------------------------------------------------------
				// Check error condition and attempt to resend if call
				// was interrupted by a signal.
				//---------------------------------------------------------
				do
				{
					m_nBytesSent = SEND(m_socket, pBuf, bytesToSend, 0);
					TranslateSocketError();
				} while (GetSocketError() == TDSocket::SocketInterrupted);

			}
		}
		break;
	}
	case TDSocket::SocketTypeUdp:
	{
		if (IsSocketValid())
		{
			if ((bytesToSend > 0) && (pBuf != NULL))
			{
				//---------------------------------------------------------
				// Check error condition and attempt to resend if call
				// was interrupted by a signal.
				//---------------------------------------------------------
				//                    if (GetMulticast())
				//                    {
				//                        do
				//                        {
				//                            m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stMulticastGroup, 
				//                                                  sizeof(m_stMulticastGroup));
				//                            TranslateSocketError();
				//                        } while (GetSocketError() == TDSocket::SocketInterrupted);
				//                    }
				//                    else
				{
					do
					{
						m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stServerSockaddr, sizeof(m_stServerSockaddr));
						TranslateSocketError();
					} while (GetSocketError() == TDSocket::SocketInterrupted);
				}

			}
		}
		break;
	}
	default:
		break;
	}

	return m_nBytesSent;
}
示例#20
0
int UDPSocket::SetReadTimeout(int seconds, int useconds)
{
	struct timeval tv;
	tv.tv_sec=seconds;
	tv.tv_usec=useconds;
	PPLSOCKET *s=(PPLSOCKET*)socket;
    if (!s) {
        SetError(275);
        return 0;
    }
#ifdef WIN32
	if (setsockopt(s->sd,SOL_SOCKET,SO_RCVTIMEO,(const char*)&tv,sizeof(tv))!=0) {
#else
	if (setsockopt(s->sd,SOL_SOCKET,SO_RCVTIMEO,(void*)&tv,sizeof(tv))!=0) {
#endif
		SetError(350);
		return 0;
	}
	return 1;
}


int UDPSocket::RecvFrom(void *buffer, int maxlen)
/*! \brief UDP-Packet empfangen
 *
 * \header \#include <ppl6.h>
 * \desc
 * Diese Funktion wartet auf ein UDP-Packet
 *
 * \param buffer Ein Pointer auf den Puffer, in den die Daten geschrieben werden sollen
 * \param maxlen Die maximale Anzahl Bytes, die in den Puffer geschrieben werden können
 * \returns Im Erfolgsfall liefert die Funktion die Anzahl gelesener Bytes zurück, im Fehlerfall -1.
 * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden
 *
 * \since Wurde mit Version 6.0.19 eingeführt
 */
{
	struct sockaddr from;
#ifdef _WIN32
	int len;
#else
	socklen_t len=0;
#endif
	PPLSOCKET *s=(PPLSOCKET*)socket;
	if (!s) {
		socket=malloc(sizeof(PPLSOCKET));
		s=(PPLSOCKET*)socket;
		s->sd=-1;
	}
	if (s->sd<0) s->sd=::socket(AF_INET,SOCK_DGRAM,0);

#ifdef _WIN32
	len=sizeof(struct sockaddr);
	int ret=::recvfrom(s->sd,(char*)buffer,maxlen,0,&from,&len);
	//int ret=::recvfrom(s->sd,(char*)buffer,maxlen,0,NULL,0);
#else
	int ret=::recvfrom(s->sd,buffer,maxlen,0,&from,&len);
#endif
	if (ret<0) {
		SetSocketError();
		return -1;
	}

	return ret;
}

int UDPSocket::GetDescriptor()
{
	if (!socket) return 0;
	PPLSOCKET *s=(PPLSOCKET*)socket;
#ifdef _WIN32
	return (int)s->sd;
#else
	return s->sd;
#endif
}


int UDPSocket::RecvFrom(void *buffer, int maxlen, CString &host, int *port)
/*! \brief UDP-Packet empfangen
 *
 * \header \#include <ppl6.h>
 * \desc
 * Diese Funktion wartet auf ein UDP-Packet
 *
 * \param buffer Ein Pointer auf den Puffer, in den die Daten geschrieben werden sollen
 * \param maxlen Die maximale Anzahl Bytes, die in den Puffer geschrieben werden können
 * \param host Pointer auf einen String, in dem die Absender-IP des Pakets gespeichert wird
 * \param port Port des Absenders
 * \returns Im Erfolgsfall liefert die Funktion die Anzahl gelesener Bytes zurück, im Fehlerfall -1.
 * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden
 *
 * \since Wurde mit Version 6.2.3 eingeführt
 */
{
	struct sockaddr_in from;
#ifdef _WIN32
	int len;
#else
	socklen_t len=0;
#endif
	PPLSOCKET *s=(PPLSOCKET*)socket;
	if (!s) {
		socket=malloc(sizeof(PPLSOCKET));
		s=(PPLSOCKET*)socket;
		s->sd=-1;
	}
	if (s->sd<0) s->sd=::socket(AF_INET,SOCK_DGRAM,0);

#ifdef _WIN32
	len=sizeof(struct sockaddr);
	int ret=::recvfrom(s->sd,(char*)buffer,maxlen,0,(sockaddr*)&from,&len);
	//int ret=::recvfrom(s->sd,(char*)buffer,maxlen,0,NULL,0);
#else
	int ret=::recvfrom(s->sd,buffer,maxlen,0,(struct sockaddr *)&from,&len);
#endif
	if (ret<0) {
		SetSocketError();
		return -1;
	}
	char hostname[1024];
	char servname[32];
	bzero(hostname,1024);
	bzero(servname,32);
	ppl6::HexDump(&from,sizeof(struct sockaddr));
	if (getnameinfo((const sockaddr*)&from,len,
		hostname,1023, servname,31,NI_NUMERICHOST|NI_NUMERICSERV)!=0) {
		host.Set("");
		*port=0;
	} else {
		host.Set(hostname);
		*port=atoi(servname);
	}

	return ret;
}


int UDPSocket::Bind(const char *host, int port)
{
	int addrlen=0;
	if (!socket) {
		socket=malloc(sizeof(PPLSOCKET));
		if (!socket) {
			SetError(2);
			return 0;
		}
		PPLSOCKET *s=(PPLSOCKET*)socket;
    	s->sd=0;
		s->proto=6;
		s->ipname=NULL;
		s->port=port;
		//s->addrlen=0;
	}
	PPLSOCKET *s=(PPLSOCKET*)socket;
	//if (s->sd) Disconnect();
	if (s->ipname) free(s->ipname);
	s->ipname=NULL;

	struct addrinfo hints, *res, *ressave;
	bzero(&hints, sizeof(struct addrinfo));
	hints.ai_flags=AI_PASSIVE;
	hints.ai_family=AF_UNSPEC;
	hints.ai_socktype=SOCK_DGRAM;
	int n;
	int on=1;
	#ifdef _WIN32
		SOCKET	listenfd;
	#else
		int listenfd;
	#endif
	// Prüfen, ob host ein Wildcard ist
	if (host!=NULL && strlen(host)==0) host=NULL;
	if (host!=NULL && host[0]=='*') host=NULL;

	if (host) {
		char portstr[10];
		sprintf(portstr,"%i",port);
		if ((n=getaddrinfo(host,portstr,&hints,&res))!=0) {
			SetError(273,"%s, %s",host,gai_strerror(n));
			return 0;
		}
		ressave=res;
		do {
			listenfd=::socket(res->ai_family,res->ai_socktype,res->ai_protocol);
			if (listenfd<0) continue;		// Error, try next one
			if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on))!=0) {
				freeaddrinfo(ressave);
				SetError(334);
				return 0;
			}
			if (::bind(listenfd,res->ai_addr,res->ai_addrlen)==0) {
				addrlen=res->ai_addrlen;
				break;
			}
			shutdown(listenfd,2);
			#ifdef _WIN32
				closesocket(listenfd);
			#else
				close(listenfd);
			#endif
			listenfd=0;

		} while ((res=res->ai_next)!=NULL);
		freeaddrinfo(ressave);
	} else {
		listenfd=::socket(AF_INET, SOCK_DGRAM, 0);
		if (listenfd>=0) {
			struct sockaddr_in addr;
			bzero(&addr,sizeof(addr));
			addr.sin_addr.s_addr = htonl(INADDR_ANY);
			addr.sin_port = htons(port);
			addr.sin_family = AF_INET;
		    /* bind server port */
    		if(::bind(listenfd, (struct sockaddr *) &addr, sizeof(addr))!=0) {
				shutdown(listenfd,2);
				#ifdef _WIN32
					closesocket(listenfd);
				#else
					close(listenfd);
				#endif
				SetError(266);
				return 0;
    		}
    		s->sd=listenfd;
    		//s->addrlen=0;
    		//connected=1;
    		return 1;
		}
	}
	if (listenfd<0) {
		SetError(265,"Host: %s, Port: %d",host,port);
		return 0;
	}
	if (res==NULL) {
		SetError(266,"Host: %s, Port: %d",host,port);
		return 0;
	}
	s->sd=listenfd;
	//s->addrlen=addrlen;
	//connected=1;
	return 1;
}
//------------------------------------------------------------------------------
//
// ConnectTCP() -
//
//------------------------------------------------------------------------------
bool TDSocket::ConnectTCP(const char *pAddr, i16 nPort)
{
	bool           bRetVal = false;
	struct in_addr stIpAddress;

	//------------------------------------------------------------------
	// Preconnection setup that must be preformed					 
	//------------------------------------------------------------------
	memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));
	m_stServerSockaddr.sin_family = AF_INET;

	hostent * pHE = NULL;
	if ((pHE = GETHOSTBYNAME(pAddr)) == NULL)
	{
#ifdef WIN32
		TranslateSocketError();
#else
		if (h_errno == HOST_NOT_FOUND)
		{
			SetSocketError(SocketInvalidAddress);
		}
#endif
		return bRetVal;
	}

	memcpy(&stIpAddress, pHE->h_addr_list[0], pHE->h_length);
	m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;

	if ((i32)m_stServerSockaddr.sin_addr.s_addr == TDSocket::SocketError)
	{
		TranslateSocketError();
		return bRetVal;
	}

	m_stServerSockaddr.sin_port = htons(nPort);

	//------------------------------------------------------------------
	// Connect to address "xxx.xxx.xxx.xxx"	(IPv4) address only.  
	// 
	//------------------------------------------------------------------

	if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) ==
		TDSocket::SocketError)
	{
		//--------------------------------------------------------------
		// Get error value this might be a non-blocking socket so we 
		// must first check.
		//--------------------------------------------------------------
		TranslateSocketError();

		//--------------------------------------------------------------
		// If the socket is non-blocking and the current socket error
		// is SocketEinprogress or SocketEwouldblock then poll connection 
		// with select for designated timeout period.
		// Linux returns EINPROGRESS and Windows returns WSAEWOULDBLOCK.
		//--------------------------------------------------------------
		if ((IsNonblocking()) &&
			((GetSocketError() == TDSocket::SocketEwouldblock) ||
			(GetSocketError() == TDSocket::SocketEinprogress)))
		{
			bRetVal = Select(GetConnectTimeoutSec(), GetConnectTimeoutUSec());
		}
	}
	else
	{
		TranslateSocketError();
		bRetVal = true;
	}


	return bRetVal;
}
示例#22
0
//------------------------------------------------------------------------------
//
// Receive() - Attempts to receive a block of data on an established		
//			   connection.	Data is received in an internal buffer managed	
//			   by the class.  This buffer is only valid until the next call	
//			   to Receive(), a call to Close(), or until the object goes out
//			   of scope.													
//																			
//------------------------------------------------------------------------------
int32 CSimpleSocket::Receive(int32 nMaxBytes)
{
    m_nBytesReceived = 0;

    //--------------------------------------------------------------------------
    // If the socket is invalid then return false.
    //--------------------------------------------------------------------------
    if (IsSocketValid() == false)
    {
        return m_nBytesReceived;
    }

    //--------------------------------------------------------------------------
    // Free existing buffer and allocate a new buffer the size of
    // nMaxBytes.
    //--------------------------------------------------------------------------
    if ((m_pBuffer != NULL) && (nMaxBytes != m_nBufferSize))
    {
        delete [] m_pBuffer;
        m_pBuffer = NULL;
    }

    //--------------------------------------------------------------------------
    // Allocate a new internal buffer to receive data.
    //--------------------------------------------------------------------------
	if (m_pBuffer == NULL)
	{
		m_nBufferSize = nMaxBytes;
		m_pBuffer = new uint8[nMaxBytes]; 
	}

    SetSocketError(SocketSuccess);

    switch (m_nSocketType)
    {
        m_timer.Initialize();
        m_timer.SetStartTime();

        //----------------------------------------------------------------------
        // If zero bytes are received, then return.  If SocketERROR is 
        // received, free buffer and return CSocket::SocketError (-1) to caller.	
        //----------------------------------------------------------------------
        case CSimpleSocket::SocketTypeTcp:
        {
            do 
            {
                m_nBytesReceived = RECV(m_socket, (m_pBuffer + m_nBytesReceived), 
                                        nMaxBytes, m_nFlags);
                TranslateSocketError();
            } while ((GetSocketError() == CSimpleSocket::SocketInterrupted));

            break;
        }
        case CSimpleSocket::SocketTypeUdp:
        {
            uint32 srcSize;
                
            srcSize = sizeof(struct sockaddr_in);

            if (GetMulticast() == true)
            {
                do 
                {
                    m_nBytesReceived = RECVFROM(m_socket, m_pBuffer, nMaxBytes, 0, 
                                                &m_stMulticastGroup, &srcSize);
                    TranslateSocketError();
                } while (GetSocketError() == CSimpleSocket::SocketInterrupted);
            }
            else
            {
                do 
                {
                    m_nBytesReceived = RECVFROM(m_socket, m_pBuffer, nMaxBytes, 0, 
                                                &m_stClientSockaddr, &srcSize);
                    TranslateSocketError();
                } while (GetSocketError() == CSimpleSocket::SocketInterrupted);
            }

            break;
        }
        default:
            break;
    }
    
    m_timer.SetEndTime();
    TranslateSocketError();

    //--------------------------------------------------------------------------
    // If we encounter an error translate the error code and return.  One 
    // possible error code could be EAGAIN (EWOULDBLOCK) if the socket is
    // non-blocking.  This does not mean there is an error, but no data is
    // yet available on the socket.
    //--------------------------------------------------------------------------
    if (m_nBytesReceived == CSimpleSocket::SocketError)
    {
        if (m_pBuffer != NULL)
        {
            delete [] m_pBuffer;
            m_pBuffer = NULL;
        }
    }

    return m_nBytesReceived;
}
示例#23
0
/*!\brief Lese-Timeout festlegen
 *
 * Mit dieser Funktion kann ein Timeout für Lesezugriffe gesetzt werden. Normalerweise
 * blockiert eine Leseoperation mit "Read" solange, bis die angeforderten Daten
 * eingegangen sind (ausser der Socket wurde mit TCPSocket::setBlocking auf "Non-Blocking"
 * gesetzt). Mit dieser Funktion kann jedoch ein beliebiger mikrosekunden genauer
 * Timeout festgelegt werden. Der Timeout errechnet sich dabei aus
 * \p seconds + \p useconds.
 * \par
 * Um den Timeout wieder abzustellen, kann die Funktion mit 0 als
 * Wert für \p seconds und \p useconds aufgerufen werden.
 *
 * @param[in] seconds Anzahl Sekunden
 * @param[in] useconds Anzahl Mikrosekunden (1000000 Mikrosekunden = 1 Sekunde)
 * @exception NotConnectedException
 * @exception InvalidSocketException
 * @exception BadFiledescriptorException
 * @exception UnknownOptionException
 * @exception BadAddressException
 * @exception InvalidArgumentsException
 */
void UDPSocket::setTimeoutRead(int seconds, int useconds)
{
	if (!connected)
		throw NotConnectedException();
	struct timeval tv;
	tv.tv_sec = seconds;
	tv.tv_usec = useconds;
	PPLSOCKET *s = (PPLSOCKET*) socket;
#ifdef WIN32
	if (setsockopt(s->sd,SOL_SOCKET,SO_RCVTIMEO,(const char*)&tv,sizeof(tv))!=0) {
#else
	if (setsockopt(s->sd, SOL_SOCKET, SO_RCVTIMEO, (void*) &tv, sizeof(tv)) != 0) {
#endif
		throwExceptionFromErrno(errno, "setTimeoutRead");
	}
}

/*!\brief Schreib-Timeout festlegen
 *
 * Mit dieser Funktion kann ein Timeout für Schreibzugriffe gesetzt werden. Normalerweise
 * blockiert eine Schreiboperation mit "Write" solange, bis alle Daten gesendet wurden.
 * Mit dieser Funktion kann jedoch ein beliebiger mikrosekunden genauer
 * Timeout festgelegt werden. Der Timeout errechnet sich dabei aus
 * \p seconds + \p useconds.
 * \par
 * Um den Timeout wieder abzustellen, kann die Funktion mit 0 als
 * Wert für \p seconds und \p useconds aufgerufen werden.
 *
 * @param[in] seconds Anzahl Sekunden
 * @param[in] useconds Anzahl Mikrosekunden (1000000 Mikrosekunden = 1 Sekunde)
 * @exception NotConnectedException
 * @exception InvalidSocketException
 * @exception BadFiledescriptorException
 * @exception UnknownOptionException
 * @exception BadAddressException
 * @exception InvalidArgumentsException
 */
void UDPSocket::setTimeoutWrite(int seconds, int useconds)
{
	if (!connected)
		throw NotConnectedException();
	struct timeval tv;
	tv.tv_sec = seconds;
	tv.tv_usec = useconds;
	PPLSOCKET *s = (PPLSOCKET*) socket;
#ifdef WIN32
	if (setsockopt(s->sd,SOL_SOCKET,SO_SNDTIMEO,(const char*)&tv,sizeof(tv))!=0) {
#else
	if (setsockopt(s->sd, SOL_SOCKET, SO_SNDTIMEO, (void*) &tv, sizeof(tv)) != 0) {
#endif
		throwExceptionFromErrno(errno, "setTimeoutRead");
	}
}

/*!\brief Auf eingehende Daten warten
 *
 * \desc
 * Diese Funktion prüft, ob Daten eingegangen sind. Ist dies der Fall,
 * kehrt sie sofort wieder zurück. Andernfalls wartet sie solange, bis
 * Daten eingehen, maximal aber die mit \p seconds und \p useconds
 * angegebene Zeitspanne. Falls \p seconds und \p useconds Null sind, und
 * keine Daten bereitstehen, kehrt die Funktion sofort zurück.
 *
 * @param[in] seconds Anzahl Sekunden, die gewartet werden soll
 * @param[in] useconds Anzahl Mikrosekunden, die gewartet werden soll
 * @return Die Funktion gibt \b true zurück, wenn Daten zum Lesen bereitstehen,
 * sonst \b false. Im Fehlerfall wird eine Exception geworfen.
 * @exception Diverse
 */
bool UDPSocket::waitForIncomingData(int seconds, int useconds)
{
	if (!connected) throw NotConnectedException();
	PPLSOCKET *s=(PPLSOCKET*)socket;
	fd_set rset, wset, eset;
	struct timeval timeout;

	timeout.tv_sec=seconds;
	timeout.tv_usec=useconds;

	FD_ZERO(&rset);
	FD_ZERO(&wset);
	FD_ZERO(&eset);
	FD_SET(s->sd,&rset); // Wir wollen nur prüfen, ob was zu lesen da ist
	int ret=select(s->sd+1,&rset,&wset,&eset,&timeout);
	if (ret<0) {
		throwExceptionFromErrno(errno, "UDPSocket::waitForIncomingData");
	}
	if (FD_ISSET(s->sd,&eset)) {
		throw OutOfBandDataReceivedException("UDPSocket::waitForIncomingData");
	}
	// Falls Daten zum Lesen bereitstehen, könnte dies auch eine Verbindungstrennung anzeigen
	if (FD_ISSET(s->sd,&rset)) {
		char buf[2];
		ret=recv(s->sd, buf,1, MSG_PEEK|MSG_DONTWAIT);
		// Kommt hier ein Fehler zurück?
		if (ret<0) {
			throwExceptionFromErrno(errno, "UDPSocket::isReadable");
		}
		// Ein Wert von 0 zeigt an, dass die Verbindung getrennt wurde
		if (ret==0) {
			throw BrokenPipeException();
		}
		return true;
	}
	return false;
}

/*!\brief Warten, bis der Socket beschreibbar ist
 *
 * \desc
 * Diese Funktion prüft, ob Daten auf den Socket geschrieben werden können.
 * Ist dies der Fall, kehrt sie sofort wieder zurück. Andernfalls wartet
 * sie solange, bis der Socket beschrieben werden kann, maximal aber die
 * mit \p seconds und \p useconds angegebene Zeitspanne.
 * Falls \p seconds und \p useconds Null sind, und
 * keine Daten gesendet werden können, kehrt die Funktion sofort zurück.
 *
 * @param[in] seconds Anzahl Sekunden, die gewartet werden soll
 * @param[in] useconds Anzahl Mikrosekunden, die gewartet werden soll
 * @return Die Funktion gibt \b true zurück, wenn Daten geschrieben werden können,
 * sonst \b false. Im Fehlerfall wird eine Exception geworfen.
 * @exception Diverse
 *
 */
bool UDPSocket::waitForOutgoingData(int seconds, int useconds)
{
	if (!connected) throw NotConnectedException();
	PPLSOCKET *s=(PPLSOCKET*)socket;
	fd_set rset, wset, eset;
	struct timeval timeout;
	timeout.tv_sec=seconds;
	timeout.tv_usec=useconds;

	FD_ZERO(&rset);
	FD_ZERO(&wset);
	FD_ZERO(&eset);
	FD_SET(s->sd,&wset); // Wir wollen nur prüfen, ob wir schreiben können
	int ret=select(s->sd+1,&rset,&wset,&eset,&timeout);
	if (ret<0) {
		throwExceptionFromErrno(errno, "UDPSocket::waitForOutgoingData");
	}
	if (FD_ISSET(s->sd,&eset)) {
		throw OutOfBandDataReceivedException("UDPSocket::waitForIncomingData");
	}
	if (FD_ISSET(s->sd,&wset)) {
		return true;
	}
	return false;
}

/*!\brief Bei Lesezugriffen blockieren
 *
 * \desc
 * Durch Aufruf dieser Funktion kann festgelegt werden, ob der Socket bei Lesezugriffen
 * blockieren soll. Nach dem Öffnen des Sockets ist dieser defaultmäßig so
 * eingestellt, dass er bei Lesezugriffen solange blockiert (wartet), bis Daten zur
 * Verfügung stehen. Wird er auf "Non-Blocking" gestellt, kehren die Lese-Funktionen
 * sofort mit einer Fehlermeldung zurück, wenn noch keine Daten bereitstehen.
 *
 * @param[in] value Der Wert "true" setzt den Socket in den Blocking-Modus, was auch der
 * Default ist. Durch den Wert "false" wird er in den Non-Blocking-Modus gesetzt.
 * @exception Diverse
 */
void UDPSocket::setBlocking(bool value)
{
	PPLSOCKET *s=(PPLSOCKET*)socket;
	if((!s) || (!s->sd)) throw NotConnectedException();
	int ret=0;
#ifdef _WIN32
	u_long v;
	if (value) {
		v=0;
		ret=ioctlsocket(s->sd,FIONBIO,NULL);
	} else {
		v=1;
		ret=ioctlsocket(s->sd,FIONBIO,&v);
	}
	if (ret==0) return;
	throwExceptionFromErrno(errno, "UDPSocket::setBlocking");
#else
	if (value)
	    ret=fcntl(s->sd,F_SETFL,fcntl(s->sd,F_GETFL,0)&(~O_NONBLOCK)); // Blocking
	else
		ret=fcntl(s->sd,F_SETFL,fcntl(s->sd,F_GETFL,0)|O_NONBLOCK);// NON-Blocking
	if (ret<0) throwExceptionFromErrno(errno, "UDPSocket::setBlocking");
#endif
}



/*!\brief Socket auf eine IP-Adresse und Port binden
 *
 * \desc
 * Diese Funktion muss aufgerufen werden, bevor man mit CTCPSocket::Listen einen TCP-Server starten kann. Dabei wird mit \p host
 * die IP-Adresse festgelegt, auf die sich der Server binden soll und mit \p port der TCP-Port.
 * Es ist nicht möglich einen Socket auf mehrere Adressen zu binden.
 *
 * @param[in] host IP-Adresse, Hostname oder "*". Bei Angabe von "*" bindet sich der Socket auf alle
 * Interfaces des Servers.
 * @param[in] port Der gewünschte TCP-Port
 * @exception OutOfMemoryException
 * @exception ResolverException
 * @exception SettingSocketOptionException
 * @exception CouldNotBindToInterfaceException
 * @exception CouldNotOpenSocketException
 */
void UDPSocket::bind(const String &host, int port)
{
	//int addrlen=0;
	if (!socket) {
		socket=malloc(sizeof(PPLSOCKET));
		if (!socket) throw OutOfMemoryException();
		PPLSOCKET *s=(PPLSOCKET*)socket;
		s->sd=0;
		s->proto=6;
		s->ipname=NULL;
		s->port=port;
		//s->addrlen=0;
	}
#ifdef _WIN32
	SOCKET listenfd=0;
#else
	int listenfd=0;
#endif

	PPLSOCKET *s=(PPLSOCKET*)socket;
	if (s->sd) disconnect();
	if (s->ipname) free(s->ipname);
	s->ipname=NULL;

	struct addrinfo hints;
	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_flags=AI_PASSIVE;
	hints.ai_family=AF_UNSPEC;
	hints.ai_socktype=SOCK_DGRAM;
	int on=1;
	// Prüfen, ob host ein Wildcard ist
	struct addrinfo *res;
	if (host.notEmpty()==true && host!="*") {
		char portstr[10];
		sprintf(portstr,"%i",port);
		int n;
		if ((n=getaddrinfo(host,portstr,&hints,&res))!=0) {
			throw ResolverException("%s, %s",(const char*)host,gai_strerror(n));
		}
		struct addrinfo *ressave=res;
		do {
			listenfd=::socket(res->ai_family,res->ai_socktype,res->ai_protocol);
			if (listenfd<0) continue; // Error, try next one
#ifdef _WIN32
			if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on))!=0) {
#else
			if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))!=0) {
#endif
				freeaddrinfo(ressave);
				throw SettingSocketOptionException();
			}
			if (::bind(listenfd,res->ai_addr,res->ai_addrlen)==0) {
				//addrlen=res->ai_addrlen;
				break;
			}
			::shutdown(listenfd,2);
#ifdef _WIN32
			closesocket(listenfd);
#else
			close(listenfd);
#endif
			listenfd=0;

		} while ((res=res->ai_next)!=NULL);
		freeaddrinfo(ressave);
	} else {
		// Auf alle Interfaces binden
		listenfd=::socket(AF_INET, SOCK_STREAM, 0);
		if (listenfd>=0) {
			struct sockaddr_in addr;
			memset(&addr,0,sizeof(addr));
			addr.sin_addr.s_addr = htonl(INADDR_ANY);
			addr.sin_port = htons(port);
			addr.sin_family = AF_INET;
			/* bind server port */
			if(::bind(listenfd, (struct sockaddr *) &addr, sizeof(addr))!=0) {
				::shutdown(listenfd,2);
#ifdef _WIN32
				closesocket(listenfd);
#else
				close(listenfd);
#endif
				throw CouldNotBindToInterfaceException("Host: *, Port: %d",port);
			}
			s->sd=listenfd;
			connected=1;
			return;
		}
	}
	if (listenfd<0) {
		throw CouldNotOpenSocketException("Host: %s, Port: %d",(const char*)host,port);
	}
	if (res==NULL) {
		throw CouldNotBindToInterfaceException("Host: %s, Port: %d",(const char*)host,port);
	}
	s->sd=listenfd;
	connected=1;
}



/*!\brief Daten schreiben
 *
 * \desc
 * Mit dieser Funktionen werden \p bytes Bytes aus dem Speicherbereich \p buffer an die Gegenstelle
 * gesendet.
 *
 * @param[in] buffer Pointer auf die zu sendenden Daten
 * @param[in] bytes Anzahl zu sendender Bytes
 * @return Wenn die Daten erfolgreich geschrieben wurden, gibt die Funktion die Anzahl geschriebener
 * Bytes zurück. Im Fehlerfall wird eine Exception geworfen.
 */
size_t UDPSocket::write(const void *buffer, size_t bytes)
{
	if (!connected)
		throw NotConnectedException();
	PPLSOCKET *s = (PPLSOCKET*) socket;
	if (!buffer)
		throw InvalidArgumentsException();
	size_t BytesWritten = 0;
	if (bytes) {
		size_t rest = bytes;
		ssize_t b = 0;
		while (rest) {
			b = ::send(s->sd, (char *) buffer, rest, 0);
			if (b > 0) {
				BytesWritten += b;
				rest -= b;
				buffer = ((const char*) buffer) + b;
			}
#ifdef WIN32
			if (b==SOCKET_ERROR) {
#else
			if (b < 0) {
#endif
				if (errno == EAGAIN) {
					waitForOutgoingData(0, 100000);
				} else {
					throwExceptionFromErrno(errno, "UDPSocket::write");
				}
			}
		}
	}
	return BytesWritten;
}

size_t UDPSocket::write(const String &str, size_t bytes)
{
	if (bytes>0 && bytes<=str.size()) {
		return write(str.getPtr(),bytes);
	}
	return write(str.getPtr(),str.size());
}

size_t UDPSocket::write(const WideString &str, size_t bytes)
{
	if (bytes>0 && bytes<=str.byteLength()) {
		return write(str.getPtr(),bytes);
	}
	return write(str.getPtr(),str.byteLength());
}

size_t UDPSocket::write(const ByteArrayPtr &bin, size_t bytes)
{
	if (bytes>0 && bytes<=bin.size()) {
		return write(bin.ptr(),bytes);
	}
	return write(bin.ptr(),bin.size());
}

size_t UDPSocket::writef(const char *fmt, ...)
{
	if (!fmt) throw IllegalArgumentException();
	String str;
	va_list args;
	va_start(args, fmt);
	str.vasprintf(fmt,args);
	va_end(args);
	return write(str);
}

#ifdef TODO

	void UDPSocket::setTimeoutRead(int seconds, int useconds)
	/*! \brief Timeout setzen
	 *
	 * \header \#include <ppl6.h>
	 * \desc
	 * Mit dieser Funktion wird der Timeout für das Empfangen von Daten gesetzt.
	 *
 * \param seconds Anzahl Sekunden
 * \param useconds Anzahl Millisekunden
 * \note Diese Funktion hat zur Zeit noch keine Auswirkungen
 * \since Wurde mit Version 6.0.19 eingeführt
 */
{
	timeout_sec=seconds;
	timeout_usec=useconds;
}
#endif

#ifdef TODO
size_t UDPSocket::sendTo(const String &host, int port, const String &buffer)
/*! \brief UDP-Packet verschicken
 *
 * \header \#include <ppl6.h>
 * \desc
 * Mit dieser Funktion wird ein UDP-Paket an den angegebenen Host verschickt.
 *
 * \param host Der Name oder die IP-Adresse des Zielrechners
 * \param port Der Port des Zielrechners
 * \param buffer Ein Pointer auf eine String-Klasse, die die zu sendenden Daten enthält
 * \returns Im Erfolgsfall liefert die Funktion die Anzahl gesendeter Bytes zurück, im Fehlerfall -1.
 * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden
 *
 * \since Wurde mit Version 6.0.19 eingeführt
 */
{
	return sendTo(host,port,(const void *)buffer.getPtr(),buffer.len());
}




size_t UDPSocket::sendTo(const String &host, int port, const void *buffer, size_t bytes)
/*! \brief UDP-Packet verschicken
 *
 * \header \#include <ppl6.h>
 * \desc
 * Mit dieser Funktion wird ein UDP-Paket an den angegebenen Host verschickt.
 *
 * \param host Der Name oder die IP-Adresse des Zielrechners
 * \param port Der Port des Zielrechners
 * \param buffer Ein Pointer auf den Puffer, der die zu sendenden Daten enthält
 * \param bytes Die Anzahl Bytes im Puffer, die gesendet werden sollen
 * \returns Im Erfolgsfall liefert die Funktion die Anzahl gesendeter Bytes zurück, im Fehlerfall -1.
 * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden
 *
 * \since Wurde mit Version 6.0.19 eingeführt
 */
{
	if (!host) {
		ppl6::SetError(194,"int UDPSocket::SendTo(==> char *host <== , int port, void *buffer, int bytes)");
		return -1;
	}
	if (!port) {
		ppl6::SetError(194,"int UDPSocket::SendTo(char *host, ==> int port <== , void *buffer, int bytes)");
		return -1;
	}
	if (!buffer) {
		ppl6::SetError(194,"int UDPSocket::SendTo(char *host, int port, ==> void *buffer <== , int bytes)");
		return -1;
	}
	if (bytes<0) {
		ppl6::SetError(194,"int UDPSocket::SendTo(char *host, int port, void *buffer, ==> int bytes <== )");
		return -1;
	}
	ppl6::CAssocArray res, *a;
	ppl6::CBinary *bin;
	if (!ppl6::GetHostByName(host,&res)) return -1;
	a=res.GetFirstArray();
	//a->List();


	int domain, type, protocol;
	domain=ppl6::atoi(a->Get("ai_family"));
	type=ppl6::atoi(a->Get("ai_socktype"));
	//protocol=ppl6::atoi(a->Get("ai_protocol"));
	struct protoent *proto=getprotobyname("UDP");
	if (!proto) {
		ppl6::SetError(395);
		return -1;
	}
	protocol=proto->p_proto;
	bin=a->GetBinary("ai_addr");
	//a->List();
	const struct sockaddr *to=(const struct sockaddr *)bin->GetPtr();
	((sockaddr_in*)to)->sin_port=htons(port);
	PPLSOCKET *s=(PPLSOCKET*)socket;
	if (!s) {
		socket=malloc(sizeof(PPLSOCKET));
		s=(PPLSOCKET*)socket;
		s->sd=-1;
	} else if ((int)s->sd>-1) {
		ppl_closesocket(s->sd);
	}
	s->sd=::socket(domain,SOCK_DGRAM,protocol);
	//sockfd=::socket(AF_INET,SOCK_DGRAM,0);
	if (s->sd<0) {
		SetSocketError();
		return -1;
	}
#ifdef _WIN32
	int ret=::sendto(s->sd,(const char*)buffer,bytes,0,to,bin->GetSize());
#else
	ssize_t ret=::sendto(s->sd,(const void*)buffer,(size_t)bytes,0,to,(socklen_t) bin->GetSize());
#endif
	if (ret<0) {
		printf ("ret: %i\n",(int)ret);
		SetSocketError();
		return -1;
	}
	//close(sockfd);
	return ret;
}



int UDPSocket::RecvFrom(CString &buffer, int maxlen)
/*! \brief UDP-Packet empfangen
 *
 * \header \#include <ppl6.h>
 * \desc
 * Diese Funktion wartet auf ein UDP-Packet
 *
 * \param buffer Ein Pointer auf eine String-Klasse, in die die Daten geschrieben werden sollen
 * \param maxlen Die maximale Anzahl Bytes, die in den Puffer geschrieben werden können
 * \returns Im Erfolgsfall liefert die Funktion die Anzahl gelesener Bytes zurück, im Fehlerfall -1.
 * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden
 *
 * \since Wurde mit Version 6.0.19 eingeführt
 */
{
	char *b=(char*)malloc(maxlen+1);
	if (!b) {
		SetError(2);
		return 0;
	}
	int ret=RecvFrom((void*)b,maxlen);
	buffer.ImportBuffer(b,maxlen);
	return ret;
}
示例#24
0
void CSocket::SetSocketError(void)
{ 
    int nError = WSAGetLastError();
    switch (nError)
    {
        case EXIT_SUCCESS:
            SetSocketError(SocketEnum::Success);
            break;
        case WSAEBADF:
        case WSAENOTCONN:
            SetSocketError(SocketEnum::Notconnected);
            break;
        case WSAEINTR:
            SetSocketError(SocketEnum::Interrupted);
            break;
        case WSAEACCES:
        case WSAEAFNOSUPPORT:
        case WSAEINVAL:
        case WSAEMFILE:
        case WSAENOBUFS:
        case WSAEPROTONOSUPPORT:
            SetSocketError(SocketEnum::InvalidSocket);
            break;
        case WSAECONNREFUSED :
            SetSocketError(SocketEnum::ConnectionRefused);
            break;
        case WSAETIMEDOUT:
            SetSocketError(SocketEnum::Timedout);
            break;
        case WSAEINPROGRESS:
            SetSocketError(SocketEnum::Einprogress);
            break;
        case WSAECONNABORTED:
            SetSocketError(SocketEnum::ConnectionAborted);
            break;
        case WSAEWOULDBLOCK:
            SetSocketError(SocketEnum::Ewouldblock);
            break;
        case WSAENOTSOCK:
            SetSocketError(SocketEnum::InvalidSocket);
            break;
        case WSAECONNRESET:
            SetSocketError(SocketEnum::ConnectionReset);
            break;
        case WSANO_DATA:
            SetSocketError(SocketEnum::InvalidAddress);
            break;
        case WSAEADDRINUSE:
            SetSocketError(SocketEnum::AddressInUse);
            break;
        case WSAEFAULT:
            SetSocketError(SocketEnum::InvalidPointer);
            break;
        default:
            SetSocketError(SocketEnum::UnknownError);
            break;	
    } 
}
示例#25
0
bool CSocket::ShutDown(SocketEnum::ShutdownMode mode)
{ 
	SocketEnum::SocketError nRetVal = (SocketEnum::SocketError)shutdown(csocket, SocketEnum::Both);
	SetSocketError(); 
	return (nRetVal == SocketEnum::Success) ? true: false;
}