I am currently working on file transfer between two mobile devices. For this, i am using socket communication. On socket using DataInput and Data Output Stream, i am able to get approximately 6 MB/s speed. But as per my use case user can select all images, videos, apk's, documents to transfer. so let's say user selected 2GB data to transfer with my app he has to wait for more than 6 minutes. so I have done some modifications.
1] On receiver side I opened up 5 ports (one for image, one for video and so on)
2] Sender will send appropriate files on corresponding ports.
3] I am sending all the files at a time parallelly using async task and receiver is receiving data in 5 different thread.
But the problem is speed still is same for 2GB it's approximately 6MB/s.
So my question is:
1] Will multiport socket increase performance?
2] if I am doing something wrong, then how can I send data parallelly on different ports on a socket?
Android devices cannot go more than 7mb/s as per my experience. Use some data monitor start file transfer on lan. You will notice its maximum speed is approximately 7mb.
Sorry i cannot comment yet so added as answer.
Related
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.
I am trying to write a 120 byte data through ble to raspberrypi from my android app(I increased the MTU to the required limit). But all I am able to transfer is first 20 bytes. When I tried to search on the internet, I see that android limits the size to 20 byte for ble transfers and I will have to send multiple 20 byte packets.
But why I tried to end the same data from nrfConnect android app, I see that the data is being transferred without any issue. Can you help me understand how nrfConnect is able to do it with you writing it as packets?
Through the data is getting truncated, i am getting GATT_SUCCESS response from raspberrypi
Just as info, I am able to send 52 bytes to our custom board with nrf52 chip from the same app
Looks like android takes care of writing more than 20 bytes of data.
Below are the two cases that I had:
Case 1:
Android app trying to write data to custom program running in nrf52 chip.
Size of data : 50 bytes.
After increase the BLE MTU on the chip side, the write was successful without any changes from app side.(gatt.writeCharacteristic(characteristic))
Case 2:
Android app trying to write data to ble program running in raspberrypi 3
Size of data 120 bytes.
Issue:Even after increasing the BLE MTU in raspberry pi, when trying to write the data only 20 bytes are received, with successful write response.
Solution: After using gatt.requestMtu(120) and calling the write character in onMtuChanged() callback, was able to send the entire data.
If I want to transfer a lot of data (e.g. 1 MB file) over BLE, what's the best way to do it?
I control both sides of the connection, but the client side is iOS/Android so only has access to GATT. I can't do anything with L2CAP.
I also can't wait for Bluetooth 4.1, 6LoWPAN, Connection-Oriented-Channels or anything like that.
I would assume the answer is to have one "request" characteristic that you write a data request to ("Give me 3000 bytes starting at byte 0"), and a "data out" characteristic that sends lots of 20 byte notifications (the maximum characteristic size) containing the data.
Is there a better way?
Yes we are using the approach you have mentioned.
Request data with the last index number(First time the index is 0)
The server send you with data with index no.Store the index no for subsequent format
continue Step 1 and 2 till the time server sends end of data-probably with index -1 or something.
Make sure you transfer the data you required in the most space efficient format.See if you can zip the files and transfer it.
You can update connection interval to small value with smallest 6*1.25 ms in remote BLE device.
Actually, BLE is designed for Low energy, small packet, low data rate.
L2cap data will be transmitted in different data channel with frequency hop. Packets TX/RX happen within each connection interval and max number of packets TX/RX in an event is restricted by specification, finally implemented by manufacture. So we can change connection interval as small as possible to increase data rate.
Refer BT 4.0 spec Vol 2, 7.8.18 LE Connection Update Command.
Try to negotiate a larger MTU than the default.
Then each notification can be larger. Even though it will be fragmented by the L2CAP layer, you will get a slightly larger throughput since the packet header will be smaller.
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.
I have an android client that functions as a central and have an app on my MAC (peripheral) that this central connects to and sends data.
At this point, I need to wait almost 100ms after I call writeCharacteristic(..) to receive the onCharacteristicWrite(..) callback. I am sending strings. If I send smaller strings, the throughput is great (understandably). When the string contains about 200 characters and I send 20 byte chunks, it takes almost a second before the entire string is seen at the peripheral. When I set the write type to NO_RESPONSE before writing the characteristic, I see no data on the peripheral.
After I connect, I have done the following to improve throughput:
Stopped discovery after services are discovered because it is an expensive operation
I set the write type to default first - When I do this, I see data on the peripheral. But, there is a significant delay. When I set the writeType to NO_RESPONSE, I see no data on the peripheral. I have no logic in onCharacteristicWrite(..) either. Sometimes, I see the data getting truncated on the peripheral.
I have set the desired connection latency to low on my mac app. Is there a way to set a value (as 7.5ms perhaps?).
When I set the write type to default and send a string of 200 characters - I split the string into 20 byte chunks. I now have 10 chunks to send. If I set characteristic value and call writeCharacteristic(..) in loop, I see no data. When I add a ~100ms delay after writeCharacteristic(..) before it executes the next iteration of the loop, I see data on the peripheral.
I see a huge increase in throughput between an iOS central - iOS peripheral. I don't see why Android central - iOS peripheral shouldn't work he same way. From my understanding, Android and iOS use the same chip.
Any reason the performance is so poor? Is there anything else I can do to improve throughput?
Please have a look at the MTU size. My experience:
Using a iOS central, the central automatically starts the MTU size negotiation with some large value. I think it is larger than 200 bytes.
On most Android devices I tested this does not start automatically but you have to start the MTU size negotiation by your app (central). If you do not do that, Android cuts your data into 20 byte pieces. This has big influence on your throughput.