Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: CBXE8 - TIdUDPClient ReceiveBuffer() no data received in Android ?


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 6 - Last Post: Apr 23, 2015 6:17 PM Last Post By: GAI CHEW KAI
GAI CHEW KAI

Posts: 117
Registered: 7/25/14
CBXE8 - TIdUDPClient ReceiveBuffer() no data received in Android ?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 22, 2015 12:38 AM
I am using Embarcadero® C++Builder XE8 Version 22.0.19027.8951 and Indy 10.

I have a Android mobile v4.1.2 and Windows 8.1 x64 connected a router.

A Win32 raw socket UDP server is running at 192.168.0.105:8080, and is confirmed mobile able to ping to 192.168.0.105 successfully and a Win32 raw socket UDP Client is able to connect and receive data sent by the UDP server.

I have the following C++ code setup for TIdUDPClient which is "udp" within a timer routine.

void ...OnButtonClick (...)
{
UnicodeString ip = L"192.168.0.105";
WORD port = 8080;

udp->Host = ip;
udp->Port = port;
udp->BufferSize = 8192;
udp->ReceiveTimeOut = 1000;
udp->Active = true;
udp->Connect();
}

void ....OnTimer (...)
{
TIdBytes buf;
UnicodeString ip = L"192.168.0.105";
WORD port = 8080;

if( udp->Connected() )
{
buf.set_length( udp->BufferSize ); // I noticed from Delphi sample, there is SetLength() but not available in CBXE8 ?
// buf.Length = 512; // I also tested this line but no data received also.

iResult = udp->ReceiveBuffer( buf, ip, port, 128 ); // already tried ReceiveBuffer( buf, 128 ) but no data received, iResult = 0 always.
}
}

QUESTIONS:

1. Why there is no data received from ReceiveBuffer() ?

2. From survey online, I cannot use TIdUDPServer OnUDPRead() event as there is "Bindings" error with Win32 UDP Server is running.

3. I also noticed to use ReceiveBuffer() in separate thread and I tested with TIdThreadComponent named "thd" source OnRun() event below:

static int cnt = 0;

void __fastcall TfMain::thdOnRun (TIdThreadComponent* Sender)
{
UnicodeString us;

us.sprintf( L"...%i", cnt++ );

lb->Text = us;

}

BUT once executed, the application crashed and break at errors below:

Project xxx.apk raised exception class Segmentation fault(11)

FMX.TextLayout.GPU:
LINE 1025: if (LRun.ImageRect.Width > 0) and (WordWrap or (Trimming <> TTextTrimming.None)) and ((LLine.Width + Rec.Glyph.Advance * FScaleFactor) > WidthLimit) then

Project xxx.apk raised exception class EListError with message 'Duplicates not allowed".
System.Generics.Collections:
Line 6181: raise EListError.CreateRes(@SGenericDuplicateItem);

4. Is there a full sample C++ source of TIdUDPClient->ReceiveBuffer() in CBXE8 as it is hard to find one, the closest I can get, is in Delphi which has another issues in translating to C++ such as the "SetLength()" API. Any good reference link will do.

Please advise.

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: CBXE8 - TIdUDPClient ReceiveBuffer() no data received in Android ?[Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 22, 2015 11:22 AM   in response to: GAI CHEW KAI in response to: GAI CHEW KAI
GAI wrote:

a Win32 raw socket UDP Client is able to connect and receive data
sent by the UDP server.

Using the exact same Indy code as your Android client? Does your Android
app have the INTERNET permission enabled? Did you verify with a network
packet sniffer that the UDP packets are actually reaching the mobile device?

buf.set_length( udp->BufferSize ); // I noticed from Delphi

set_length() is the setter method for the Length property. Use the property,
not the setter directly:

buf.Length = udp->BufferSize;


iResult = udp->ReceiveBuffer( buf, ip, port, 128 ); // already tried ReceiveBuffer(
buf, 128 ) but no data received, iResult = 0 always.

You set the TIdUDPClient::ReceiveTimeout property to 1sec, but are then overwriting
it with a 128ms timeout when calling ReceiveBuffer(). Are you sure there
is actually data available within that 128ms window of time? Did you try
removing the 128 parameter so the ReceiveTimeout property gets used?

iResult = udp->ReceiveBuffer( buf, ip, port );


iResult = udp->ReceiveBuffer( buf );


1. Why there is no data received from ReceiveBuffer() ?

There is not enough information to answer that.

2. From survey online, I cannot use TIdUDPServer OnUDPRead() event
as there is "Bindings" error with Win32 UDP Server is running.

I do not understand what you are referring to. Please clearify.

3. I also noticed to use ReceiveBuffer() in separate thread and I
tested with TIdThreadComponent named "thd" source OnRun() event
below:
<snip>
BUT once executed, the application crashed and break at errors below:

It is not safe to access UI components from outside the main UI thread.

4. Is there a full sample C++ source of TIdUDPClient->ReceiveBuffer()
in CBXE8

No.

--
Remy Lebeau (TeamB)
GAI CHEW KAI

Posts: 117
Registered: 7/25/14
Re: CBXE8 - TIdUDPClient ReceiveBuffer() no data received in Android ?[Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 22, 2015 3:24 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
"Using the exact same Indy code as your Android client?"
- Yes, Android Client is using Indy code but UDP Server is Win32 raw socket coding.
- The packet is simple such as:

<STX>RAW TEXT<ETX>

- By the way, do I need to append a NULL character ?

"Does your Android app have the INTERNET permission enabled?"
- Which permission, the Android device setting itself or the router ?

"Did you verify with a network packet sniffer that the UDP packets are actually reaching the mobile device?"
- The UDP Client is able to establish connection itself but no connection detected at the UDP server side.
- The mobile is connected via WIFI, the same time USB connected for debugging on mobile, how to check using sniffer upon WIFI connected mobile ?

"Did you try removing the 128 parameter so the ReceiveTimeout property gets used?
- Yes, I specified 1000 as well instead of 128 but will verify again today.

"I do not understand what you are referring to. Please clearify."
- The mobile indicated that TIdUDPServer cannot establish bindings of 192.168.0.105:8080 if the "Bindings" proptery of TIdUDPServer held at mobile is specified as 192.168.0.105:8080 where on the Win32 UDP Server side is also using 192.168.0.105:8080

"It is not safe to access UI components from outside the main UI thread."
- Does this means, only non-UI codes is allowed ( eg. us.sprintf() ) ?

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: CBXE8 - TIdUDPClient ReceiveBuffer() no data received in Android?[Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 22, 2015 4:27 PM   in response to: GAI CHEW KAI in response to: GAI CHEW KAI
GAI wrote:

"Using the exact same Indy code as your Android client?"
- Yes, Android Client is using Indy code but UDP Server is Win32
raw socket coding.

That is not what I asked. You said that a Win32 UDP client is able to receive
the data. Is that client using the same Indy code that the Android app is
using?

And you keep saying "raw socket". Are you referring to an actual RAW socket
(SOCK_RAW socket type)? Or do you mean "raw" as in "plain ordinary socket
API calls"?

- By the way, do I need to append a NULL character ?

No.

"Does your Android app have the INTERNET permission enabled?" -
Which permission, the Android device setting itself or the router ?

The Android device itself. Your Android app manifest needs to include the
INTERNET permission, and the device user (you) needs to approve it when the
app is run, in order to use sockets.

- The UDP Client is able to establish connection itself but no
connection detected at the UDP server side.

That is not what I asked. And there are no "connections" in UDP.

Does the UDP server require a UDP client to send a packet to the server before
it will then send packets to the client? If so, are you sending that packet?
Otherwise, is the server sending the packets using a subnet broadcast?

- The mobile indicated that TIdUDPServer cannot establish bindings of
192.168.0.105:8080 if the "Bindings" proptery of TIdUDPServer held at
mobile is specified as 192.168.0.105:8080 where on the Win32 UDP
Server side is also using 192.168.0.105:8080

When you configure the TIdUDPServer.Bindings, you must specify local IP
addresses only. Your Android client cannot bind to 192.168.0.105 as that
IP does not belong to your Android device. It is the IP of the remote server.
You must use the IP that is assigned to Android's local WiFi adapter. Or
just leave the IP blank so Indy can bind to all available IPs.

+"It is not safe to access UI components from outside the main UI
thread."+ - Does this means, only non-UI codes is allowed ( eg.
us.sprintf() ) ?

Yes. If you want to access a UI control, you must synchronize with the main
UI thread, such as with the TThread.Synchronize() or TThread.Queue() method,
or Indy's TIdSync or TIdNotify class.

--
Remy Lebeau (TeamB)
GAI CHEW KAI

Posts: 117
Registered: 7/25/14
Re: CBXE8 - TIdUDPClient ReceiveBuffer() no data received in Android?[Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 22, 2015 8:32 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
"Does the UDP server require a UDP client to send a packet to the server before it will then send packets to the client?"
- Yes, you are right, I forgot to send to UDP server first in order to receive its message.
- Is working fine now.

Thanks for the great hint :o)
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: CBXE8 - TIdUDPClient ReceiveBuffer() no data received in Android?[Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 22, 2015 5:07 PM   in response to: GAI CHEW KAI in response to: GAI CHEW KAI
GAI wrote:

"Using the exact same Indy code as your Android client?"
- Yes, Android Client is using Indy code but UDP Server is Win32
raw socket coding.

That is not what I asked. You said that a Win32 UDP client is able to receive
the data. Is that client using the same Indy code that the Android app is
using?

And you keep saying "raw socket". Are you referring to an actual RAW socket
(SOCK_RAW socket type)? Or do you mean "raw" as in "plain ordinary socket
API calls"?

- By the way, do I need to append a NULL character ?

No.

"Does your Android app have the INTERNET permission enabled?" -
Which permission, the Android device setting itself or the router ?

The Android device itself. Your Android app manifest needs to include the
INTERNET permission, and the device user (you) needs to approve it when the
app is run, in order to use sockets.

- The UDP Client is able to establish connection itself but no
connection detected at the UDP server side.

That is not what I asked. And there are no "connections" in UDP.

Does the UDP server require a UDP client to send a packet to the server before
it will then send packets to the client? If so, are you sending that packet?
Otherwise, is the server sending the packets using a subnet broadcast?

- The mobile indicated that TIdUDPServer cannot establish bindings of
192.168.0.105:8080 if the "Bindings" proptery of TIdUDPServer held at
mobile is specified as 192.168.0.105:8080 where on the Win32 UDP
Server side is also using 192.168.0.105:8080

When you configure the TIdUDPServer.Bindings, you must specify local IP
addresses only. Your Android client cannot bind to 192.168.0.105 as that
IP does not belong to your Android device. It is the IP of the remote server.
You must use the IP that is assigned to Android's local WiFi adapter. Or
just leave the IP blank so Indy can bind to all available IPs.

+"It is not safe to access UI components from outside the main UI
thread."+ - Does this means, only non-UI codes is allowed ( eg.
us.sprintf() ) ?

Yes. If you want to access a UI control, you must synchronize with the main
UI thread, such as with the TThread.Synchronize() or TThread.Queue() method,
or Indy's TIdSync or TIdNotify class.

--
Remy Lebeau (TeamB)
GAI CHEW KAI

Posts: 117
Registered: 7/25/14
Re: CBXE8 - TIdUDPClient ReceiveBuffer() no data received in Android?[Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 22, 2015 7:13 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
"Does the UDP server require a UDP client to send a packet to the server before it will then send packets to the client?"
- Yes, you are right, I have forgotten to send something to UDP server first, as to allow UDP Server to send to the current client to receive the message.
- Is working fine now, here is the codes that works:

udp->Send( L"--- MOBILE ---" ); // NOTE: This line is important to trigger UDP Server to send message to the current connected client, without this, ReceiveBuffer() always returns 0.

buf.Length = udp->BufferSize;

iResult = udp->ReceiveBuffer( buf, 2000 ); // TIdUDPClient->ReceiveTimeout is set to 3000ms.

s = BytesToString( buf, 0, iResult );

Under AndroidManifest.Template.xml:
...
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
...

Thanks again Remy, for the great hint :o)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02