Push notification from server to client using UDP - android

We want to build a simple data sharing application where 2 Android mobiles (or computers) connected on any internet (wifi/network) upload and download their data to the server through HTTPS.
e.g. A wants to send data to B. A will trigger a "put" like HTTPS API and upload the data to the bucket of B. B will call the "get" like HTTPS API and download its content.
Now the issue is that the communication between A and B is demand based. It can happen after minutes, hours or days. If we go with HTTPS way, then we will have to keep B in a long polling to server which will eat out the resources for days when there is no message. If we poll every minute or 2 then the communication will not happen in near real time.
To counter this problem, we have come up with following idea:
Whenever mobile registers to internet, it creates a UDP port and
binds to it
It makes 1 time HTTPS connection to server and sends its IP
address and port
There can be optional dummy data exchange between server and client
using UDP (to and from)
After this client doesn't have any active connection and remains
on the same internet; It continuously waits on the UDP
port for data to be received; If internet changes then again
repeat from step-1
When data is received for the given client, then server sends
some predefined dummy UDP data to client as a wake up call. This
data is continuously sent until the client bucket is read via HTTPS
Upon identifying the data received on UDP, client makes an HTTPS
connection to server and reads its intended data from its bucket and
closes; Server identifies this and stops UDP
In theory this solution looks fine. But from internet I came across following problems for which I will require answers:
What kind of IP address and port should be sent to server from
client? Is it the ISP/network provided IP or something else?
How server would identify the exact client to send some UDP data?
e.g. if 2 mobiles on the same internet have same IP and ports
In C socket library, there are 2 ways of UDP connections: (1)
connect() and then just send()/recv() (2) Directly
sendto()/recvfrom() using IP addresses. Which should be used in
this scenario?
Besides above question, any improvement on the actual way of "push notification" described above is welcome.

You need to take care of clients behind NAT, for that you can use UDP Hole Punching.
Let A and B be the two hosts, each in its own private network; NA and
NB are the two NAT devices with globally reachable IP addresses EIPA
and EIPB respectively; S is a public server with a well-known globally
reachable IP address.
A and B each begin a UDP conversation with S; the NAT devices NA and NB create UDP translation states and assign
temporary external port numbers EPA and EPB
S examines the UDP packets
to get the source port used by NA and NB (the external NAT ports EPA
and EPB)
S passes EIPA:EPA to B and EIPB:EPB to A
A sends a packet to
EIPB:EPB.
NA examines A's packet and creates the following tuple in
its translation table: {Source-IP-A, EPA, EIPB, EPB}
B sends a packet
to EIPA:EPA
NB examines B's packet and creates the following tuple in
its translation table: {Source-IP-B, EPB, EIPA, EPA}
Depending on the
state of NA's translation table when B's first packet arrives (i.e.
whether the tuple {Source-IP-A, EPA, EIPB, EPB} has been created by
the time of arrival of B's first packet), B's first packet is dropped
(no entry in translation table) or passed (entry in translation table
has been made).
Depending on the state of NB's translation table when
A's first packet arrives (i.e. whether the tuple {Source-IP-B, EPB,
EIPA, EPA} has been created by the time of arrival of A's first
packet), A's first packet is dropped (no entry in translation table)
or passed (entry in translation table has been made).
At worst, the
second packet from A reaches B; at worst the second packet from B
reaches A. Holes have been "punched" in the NAT and both hosts can
communicate.

Related

Websocket giving various numbers depending on OS

I'm doing a little test where I send out a short string(4-8 bytes) to a client every 0.5 seconds from a Node.js server using ws. The client is either using iOS/Android or a web browser. The client does not send anything back to the server, except for TCP-ACKS I suppose. The weird thing is, when I'm debugging the app in iOS using XCode network report, I can only see that the client sends out some bytes(approx 500) when the connections establishes, probably during the HTTP handshake. The remaining time ZERO data is going out from the device, there is only data coming in. The same results is achieved when receiving data in Chrome and tracking the data using Nettop.
The thing that makes so confused is that on the Android, almost the same amount of data that goes in to the device goes out when inspecting the network usage with Android profiler/Battery Historian/TrafficStats. I have tried using different libraries for the Websocket implementation and using different Android devices.
I have a hard time believing the ACKS sent out by the android is as big as the message received, even though it's just a small string of four characters.
So my questions are:
Could the case be that Nettop/XCode network report is simply ignoring all the ACKS, so in reality as much data is sent out in Chrome/iOS as in Android?
Is there something 'Wrong' with the libraries used in Android or could it be something with its operating system?
Could an ACK be as big as a simple TCP-package with 4 characters in it?
The result below when using Websocket
The data received/transmitted when using Android Battery Historian
The data received/transmitted on iOS using Network Report
Could an ACK be as big as a simple TCP-package with 4 characters in it?
An ACK consists of the IP and the TCP header and no payload. With IPv4 this means at least 20 bytes IP header and 20 bytes TCP header, i.e. 40 bytes. A packet with 4 bytes payload is only larger by 4 bytes, i.e. 44 bytes or just 10%.
The network report in Android shows 68350 in vs. 61370 in bytes, which is a difference of 11%. This matches the expected difference.
I'm not familiar with what iOS measure here, but it probably either measures only the application payload (i.e. the 4 bytes) or simply ignores packets with no payload, i.e. the ACK's.

Dead connection message and delivery receipt received delay in stream management - MongooseIM server 2.0.0

I have enable stream management in both side client or server. I have two users A and B. Both users are online.Then user A suddenly lose his connection. but A user still appear online on user B and as well as on server. During that time user B sending message on user A. Those message are not lost but when user A is appear online again it will receive those message after 2-3 minute.and i will get message stanza on Offline storage and delivery receipt i will got on SM storage.This issue same occur on one to one chat and mucLight. have i need to customized any mongooseIM modules. Please guide me why users received delay message when their are lost his connection. is it possible to changed SM storage to offline storage(MAM). here's link for same issue i have found same issue on this link (https://www.ejabberd.im/faq/tcp) but have not lost my messages but just received it delay.
I am use smack-4.2 lib on my Android app.and following code used to enabled stream management in XMPPTCPConnection.
static{
XMPPTCPConnection.setUseStreamManagementDefault(true);
XMPPTCPConnection.setUseStreamManagementResumptionDefault(true);
}
Here's my ejabbered.cfg file for mod_stream_management module
{mod_stream_management, [
% default 100
% size of a buffer of unacked messages
% {buffer_max, 100}
% default 1 - server sends the ack request after each stanza
% {ack_freq, 1}
% default: 600 seconds
% {resume_timeout, 600}
]},
I have also enable following module on my config file
%% Only archives for c2c messages, good performance.
{mod_mam_odbc_user, [pm]},
{mod_mam_cache_user, [pm]},
% {mod_mam_mnesia_dirty_prefs, [pm]},
% {mod_mam_odbc_arch, [pm, no_writer]},
{mod_mam_odbc_async_pool_writer, [pm]},
{mod_mam, []}
I found little solution here smack connect to xmpp server with previous stream id but its not work on mongooseIM-2.0 server.
Thank you in advanced.
I'm assuming below that user A, when they reconnect, is not using Stream Resumption (as defined by XEP-0198: Stream Management) and merely starting a new session.
This means that on the server side there's still a dangling process waiting for Stream Resumption to happen. When user A is already reconnected to the server, the dangling process times out (which takes resume_timeout seconds) and sends the messages it had stored for delivery in the outgoing message buffer.
If you don't like this behaviour, you can do one of these:
a) (not advised) disable Stream Management and send a Message Archive Management query (that is use mod_mam) to have the most up to date conversation state each time you establish a new connection to the server
b) leave Stream Management enabled, but use Stream Resumption if only possible; that is, you always try to resume the previous session, unless you don't have the previous session ID or the server rejects the resumption request; ideally you would also use Message Archive Management
c) use Delayed Delivery aka mod_offline, but risk that in some rare cases, if you use multiple devices, the messages might be sent to a wrong device; for example, if you have a phone and a laptop, it might happen that your messages will reach the laptop, but never reach the phone
Did you try using mod_ping and configure on ejabbered.cfg file.
{mod_ping, [{send_pings, true}]},
fore more details please follow this link mod_ping

Get tank volume with ODBII in android

I want to receive the remaining tank volume and the current mileage of my car by using OBD II.
Therefore I have bought an OBDII Bluetooth Adapter for my car. I am using the
AndroidBluetoothChat for connecting to devices and establishing a connection, through I can send and receive information.
But when I try to connect to my OBD2 Adapter, I get: Unable to connect.
The OBD2 Adapter is always discoverable and I can pair them normally. Why is that?
The next question is, once i have established a connection, how can I receive Informationen like speed, mileage etc.
I am still a beginner and gratefull for every hint.
i'm in your same project :D
I start with BluetoothChat for understand how use Bluetooth and all works fine.... At the beginning you can chat with your OBD by sending Pids in the EditText from BluetoothChat...
But remember that you need a \r (carriage return) after every commands that you send.
For example if you need the RPM, send a string like "010c\r" and you get a response like 10c410cxx where xx is the value that you must divide by 4 for get the real RMP...
See every pids and data transformation in this table...
REMEMBER that for work the ELM327 (your obd device) need that the car
is ON half turn key or total or you don't get data but only error!
For the pids that you need (if your car support them) you can see all of them in the wikipedia page that i liked.
If you want an automatic dynamic comunication with obd you must change the comunication of the BluetoothChat with some Queue or ArrayList of commands and send them continuosly.....
REMEMBER that the ELM327 can manage one command each time....so send
the first command and wait the response... and again send another
command an wait response...and so on...

How to start a method in the same time on 2 devices

I have 2 android phones phones, both connected to the same wifi, both with bluetooth.
I want some method that syncs somehow the phones and starts a function on the same time on both phones.
For example playing a song at the same time.
I already tried with bluetooth but its with lag, sometimes 0.5 secs. I want something in +- 0.01sec if possible.
Someone suggesting playing it in the future with 2-3 seconds, sending the time-stamp, but how do you sync the internal clocks of the devices then ?
Before calling that particular method, try to measure the latency between the two devices:
1.First device says Hi(store the current time)
2.Second device receives the Hi.
3.Second device says back Hi !!
4.First device receives the Hi.((storedTime - currentTime) / 2 )
Now you have the latency, send your request to second device to start your particular method and start it on first one after the latency.
Try to measure the latency 5 to 10 times to be more accurate.
you have a way to transfer data between the devices right ?
if so you can send a time-stamp which is in the future,
ex: if the present time stamp is 1421242326 you send 1421242329 or something and start the function at that time on both devices.
Basically use #Dula's suggestion (device 1 sends command to device 2 and gives a "start time" which lies in the future). Both devices then start the action at the same time (in the future).
To make sure that the devices are synchronized, you can use a server-based time sync (assuming that both devices have Internet access). To do this, each device contacts the same server (using NTP, or HTTP-based NTP, or contacts a known HTTP server, like www.google.com and uses the value in the "Date" header of the HTTP response). The "server-date" is compared to the system clock on the device, and the difference is the "time-offset from server-time". The time-offsets can be used to synchronize on the "server-time", which is then used as the time base for the actual action (playing the media, etc.).
If your WiFi router allows clients to talk to each other (many public hotspots disable this), you could implement a simple socket listener on one (or each) device and have the initiating device broadcast a message.
For more complicated things and network flexibility, I've had good success with connected sessions using AllJoin. There is a bit of a learning curve to do interesting things, but the simple stuff is pretty easy once you understand the architecture.
Use a server to provide a synchronous event to just the two clients who have decclared their mutual affinity (random as a parm and pair serializer Partner-1 or Partner-2 which they share prior to their respectve calls for the sync event).
Assume both clients on same subnet (packets from 2 events serialized on the server , arrive across the network at the 2 clients simultaneously client-side) This provides synchronous PLays by 2 , bound clients.
The event delivered by server is either a confirm to play queued selected track OR a broadcast( decoupled, more formal)
The only tricky thing is the server side algorythm implementing this:
Queue a pair of requests or error
Part1, part2 with same Random value constitute valid pair if both received before either times out.
On a valid pair schedule both to the same future event in their respective , committed responses.
OnSchedule do the actual IO for 2 paired requests. Respective packets will arrive back at respective clients at same time, each response having been subject to equal network latency
Ng if two diff carrier 4G or lte networks involved. (Oops)
This thing is possible via socket, you will send a event via socket then the other device receive that event. For learn socket io chat
maybe it's not the answer you are looking for but i think that due to the high precision you are wanting , you should look for a push technology, i advice you to take look at SignalR. It's real time technology which gives you abstraction of sending methods , it have a built-in methods like Clients.All.Broadcast that fit your needs.
You can try to use some MQTT framework to send message between two device, or into a set with more number of devices.

why does android udp-socket lose packets using the method of socket.recieve()?

I just try to use the recieve() method of the socket.
When I send the data of a short String,as "send data",for 100
times,the recieve() function performs well.
While I send the data of a long String,as "send data to the
client,send data to the client,send data to the client,send data to
the client,send data to the client,send data to the client,send data
to the client,send data to the client",for 100 times,the recieve()
function cannot performs well.
In android project:
It just recieved about 30 packets, that is, other 70 packets are lost when I use another computer to send pakcets. But I checked the recieve buffer size, it is adequate to contain 100 packets above.
It recieves all the 100 packets when I use the localhost address to test. And I used the capturing tool named wireshark to capture the packets and the capturing tool can capture all the 100 packets everytime.
So I can eliminate the possibility of that another computer did not send all the packets.So I included that the problem exists in the emulator.
The above two cases both happened in android project,so the recieve buffer size is the same,
why in the former it will lose packets??
In java project:It recieves all the 100 packets too.
If you need all the packets then you should use TCP/IP protocol. In UDP protocol you can lose data because it is doesnot support reliable connection like Tcp/ip. UDP is designed to be faster at transferring data at the cost of unreliable connection. Based on network routing the packets you received could also arrive in different order.
Emulator TCP/IP stack's udp buffer size is smaller than the computer. So if the UDP buffer fills up, the emulator TCP/IP stack starts dropping packet. The PC TCP/IP stack pushes data at faster rate which the emulator can't handle. You can try reducing the rate at sender end to avoid filling the emulator buffer or increase the receive socket buffer size of android app to higher value by using the SO_RCVBUF socket option.

Categories

Resources