コード例 #1
0
ファイル: DatagramSocket.cpp プロジェクト: acornejo/CDL
    int DatagramSocket::read(DatagramPacket &pkt)
    {
		int numbytes;
		sockaddr_in addr;
		socklen_t addr_len=sizeof(addr);

		if ((numbytes=recvfrom(*((socket_t*)m_sock), (char *)pkt.getBuffer().getData(), pkt.getBuffer().getLength(), 0,
						(sockaddr *)&addr, &addr_len)) == -1)
		{
			Error_send("Unable to receive packet from UDP socket\n");
		}

        pkt.setPort(addr.sin_port);
		pkt.setAddress(InetAddress(inet_ntoa(addr.sin_addr)));
		pkt.setLength(numbytes);

		return numbytes;
    }
コード例 #2
0
//==============================================================================
// PlainDatagramSocketImpl::receive
//
//==============================================================================
void PlainDatagramSocketImpl::receive(DatagramPacket& p)
{
	testSocketIsValid();

	sockaddr_in remoteAddr;
	cel_socklen_t addrLen;
	sockaddr* pRemoteAddr = reinterpret_cast<struct sockaddr*>(&remoteAddr);
	int recvLength;

	//
	// The following code is placed within a while() block to attempt to unify
	// the behaviour on multiple platforms.  If this datagram socket has been
	// used to send a dataram packet, an ICMP response may be received to
	// indicate that the send request was unsuccessful.  This behaviour is not
	// always helpful and is not guaranteed to occur (but seems to on Windows).
	// There is a far greater liklihood of this behaviour occurring on all platforms
	// when the socket has been connected to a particular host.  For this reason,
	// connect errors are ignored unless the socket has been connected.
	//
	while(true)
	{
		// simulate SO_TIMEOUT
		if(m_nTimeoutMS && !NetUtils::SelectSocket(m_rpSocketDescriptor.get(), m_nTimeoutMS,true,false))
		{
			static const String err(QC_T("receive timed out"));
			throw SocketTimeoutException(err);
		}

		int flags = 0;
		addrLen = sizeof(remoteAddr);
		recvLength = recvfrom(m_rpSocketDescriptor->getFD(),
		                      (char*) p.getData(),
		                      p.getLength(),
		                      flags,
		                      pRemoteAddr,
		                      &addrLen);

		if(recvLength < 0)
		{
			const int errorNum = NetUtils::GetLastSocketError();

			// Failure of recvfrom may be cause by the buffer length being smaller
			// than the message (in which case we silently ignore it, and set the
			// received length equal to the buffer length supplied), or due to
			// some other serious problem which will result in a SocketException
			//
			if(errorNum == QC_EMSGSIZE)
			{
				recvLength = p.getLength();
				break;
			}
			else if(!isConnected() && (errorNum == QC_ECONNRESET || errorNum == QC_ECONNABORTED || errorNum == QC_EHOSTUNREACH))
			{
				// See detailed comment above
				continue;
			}
			else
			{
				static const String err(QC_T("error calling recvfrom "));
				String errMsg = err + NetUtils::GetSocketErrorString(errorNum);
				throw SocketException(errMsg);
			}
		}
		else
		{
			break;
		}
	}
	
	//
	// Note: this test should migrate to the InetAddress class
	//
	if(addrLen != sizeof(sockaddr_in))
	{
		static const String err(QC_T("recvfrom() returned invalid address size"));
		throw SocketException(err);
	}

	//
	// Update the DatagramPacket with the address/length info
	//
	p.setPort(ntohs(remoteAddr.sin_port));
	p.setAddress(InetAddress::FromNetworkAddress(pRemoteAddr, addrLen).get());
	p.setLength(recvLength);

	if(Tracer::IsEnabled())
	{
		Tracer::TraceBytes(Tracer::Net, Tracer::Low, QC_T("Datagram rcvd:"), p.getData(), recvLength);
	}
}