public int RecvTestPacket(ref ushort pktType, ref int seq, byte[] payload, ref int payloadSize){
	var bufSize = m_recvBuf.data.Length;
	var recvRet = RecvFrom(m_recvBuf.data, 0, ref bufSize, SocketFlags.None, ref m_recvAddr);
	
	if((m_lastNetError == SocketError.Success) && (recvRet >= HEADER_SIZE)){
	   m_recvBuf.position = 0;
	   var mc = AmNetUtil.ntohl(m_recvBuf.readUnsignedInt());
	   if(mc != MAGIC_COOKIE){
	       m_lastNetError = SocketError.SocketError;
	   }
	   else {
	       pktType     = AmNetUtil.ntohs(m_recvBuf.readUnsignedShort());
	       var pktlen  = AmNetUtil.ntohs(m_recvBuf.readUnsignedShort());
	       if(payloadSize < (pktlen - HEADER_SIZE)){
		   m_lastNetError = SocketError.SocketError;		   
	       }
	       else {
		   payloadSize = (int)pktlen - (int)HEADER_SIZE;
		   seq         = AmNetUtil.ntohl(m_recvBuf.readInt());
		   if(payloadSize > 0){
		       AmByteArray.Memcpy(payload, m_recvBuf, payloadSize);
		   }
		   m_lastNetError = SocketError.Success;
	       }
	   }	   
	}
	
	return recvRet;
    }    
    public UDPingClient(string serverAddr, int serverPort, int bindBasePort = 5730){
	int  retry = 0;
	bool isError = false;

	m_sendBuf = new AmByteArray(SEND_BUFFER_SIZE);
	m_recvBuf = new AmByteArray(RECV_BUFFER_SIZE);	
	
	m_sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

	try {
	    m_sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
	    m_sock.Blocking = false;
	    m_sendAddr = new IPEndPoint(IPAddress.Parse(serverAddr), serverPort);
	    m_recvAddr = new IPEndPoint(IPAddress.Any, 0);
	}
	catch (SocketException e){
	    m_lastNetError = e.SocketErrorCode;
	    isError = true;
	    goto wayout;
	}
	catch (Exception e){
	    m_lastNetError = SocketError.SocketError;
	    isError = true;
	    goto wayout;
	}
	
	while(retry < 10){
	    var bindAddr = new IPEndPoint(IPAddress.Any, bindBasePort + retry);
	    try {
		m_sock.Bind(bindAddr);
		break;
	    }
	    catch (SocketException e){
		if(e.SocketErrorCode == SocketError.AddressAlreadyInUse){ ++retry; continue; }
		else {
		    m_lastNetError = e.SocketErrorCode;
		    isError = true;
		    break;
		}
	    }
	    catch (Exception e){
		m_lastNetError = SocketError.SocketError;
		isError = true;
		break;
	    }
	}

    wayout:
	
	if(isError){
	    if(m_sock != null){ Dispose(); }
	}
	else {
	    m_lastNetError = SocketError.Success; 
	}
    }
    public int SendTestPacket(ushort pktType, int seq, byte[] payload, int payloadSize){
	var    pkt   = m_sendBuf;
	int    len   = 0;

	pkt.position = 0;
	pkt.writeUnsignedInt(AmNetUtil.htonl(MAGIC_COOKIE));    len += 4;
	//pkt.writeUnsignedInt(MAGIC_COOKIE);                     len += 4;
	pkt.writeUnsignedShort(AmNetUtil.htons(MSG_TYPE_ECHO)); len += 2;
	pkt.writeUnsignedShort(AmNetUtil.htons((ushort)0));     len += 2;
	pkt.writeInt(AmNetUtil.htonl(seq));                     len += 4;
	if(payloadSize > 0){
	    AmByteArray.Memcpy(pkt, payload, payloadSize); len += payloadSize;
	}	
	pkt.position = 6;
	pkt.writeUnsignedShort(AmNetUtil.htons((ushort)len));
	
	return SendTo(pkt.data, 0, ref len, SocketFlags.None, m_sendAddr);
    }